<p>有一個渲染使用者回應的元件</p>
<p>
從「react」匯入React;
const User = React.memo(function({id, name, isSelected, ...other}) {
返回 (
{名稱} - {isSelected && “已選擇”}
);
});
導出預設使用者;</pre>
</p>
<p>以及渲染使用者卡的父元件</p>
<p>
從「react」匯入React;
函數應用程式(){
const [用戶,setUsers] = React.useState([
{id:1,名稱:「John Doe #1」},
{id:2,名稱:「John Doe #2」},
{id:3,名稱:「John Doe #3」}
]);
const [selectedUserId, setSelectedUserId] = React.useState(null);
返回 users.map((用戶) => {
const isSelected = selectedUserId === user.id;
返回 (
<使用者
{...使用者}
密鑰={用戶.id}
已選擇={已選取}
onClick={() =>; setSelectedUserId(user.id)}
>>
);
});
}
導出預設應用程式;</pre>
</p>
<p>任務是「選擇使用者後避免重新渲染其他使用者卡」我嘗試使用 React.useCallback
鉤子,這是我的第一個實作</p>
<p>
從「react」匯入React;
const User = React.memo(function({id, name, isSelected, ...other}) {
返回 (
{名稱} - {isSelected && “已選擇”}
;
);
});
function Application() {
const [users, setUsers] = React.useState([
{id: 1, name: "John Doe #1"},
{id: 2, name: "John Doe #2"},
{id: 3, name: "John Doe #3"}
]);
const [selectedUserId, setSelectedUserId] = React.useState(null);
const handleSelectUser = React.useCallback((userId) => () => {
setSelectedUserId(userId);
}, []);
return users.map((user) => {
const isSelected = selectedUserId === user.id;
return (
<User
{...user}
key={user.id}
isSelected={isSelected}
onClick={handleSelectUser(user.id)}
/>
);
});
}
export default Application;</pre>
</p>
<p>在這種情況下,<code>React.useCallback</code> 傳回一個具有新引用的匿名函數</p>
<p><strong>結果:每次點擊後所有用戶卡仍重新呈現</strong></p>
<p>我決定將這個匿名函數包裝在 <code>React.useCallback</code></p>
<p>
<pre class="brush:js;toolbar:false;">import React from "react";
const User = React.memo(function({id, name, isSelected, ...other}) {
return (
<div {...other}>
{name} - {isSelected && "Selected"}
</div>
);
});
function Application() {
const [users, setUsers] = React.useState([
{id: 1, name: "John Doe #1"},
{id: 2, name: "John Doe #2"},
{id: 3, name: "John Doe #3"}
]);
const [selectedUserId, setSelectedUserId] = React.useState(null);
const handleSelectUser = React.useCallback((userId) => {
return React.useCallback(() => {
setSelectedUserId(userId);
}, []);
}, []);
return users.map((user) => {
const isSelected = selectedUserId === user.id;
return (
<User
{...user}
key={user.id}
isSelected={isSelected}
onClick={handleSelectUser(user.id)}
/>
);
});
}
export default Application;</pre>
</p>
<p>問題解決了,但還有一個問題,我做對了嗎? React 團隊說:<em>不要在循環、條件或巢狀函數內呼叫 Hooks</em>,我會得到什麼副作用? </p>
<p>附註不要碰<code>用戶</code>組件</p>
解釋為什麼不能在鉤子內部調用鉤子(並期望它一致且可靠地工作)
為什麼你不能在鉤子內部調用鉤子- 去這裡進行超深入的研究,其中的上下文比我在這個答案中需要提供的更多https://overreacted.io/why-do-hooks -rely-on-call-order/
#您的解決方案之所以有效,是因為儘管“違反了規則”,但對掛鉤的調用順序始終相同......直到用戶被添加或從狀態中刪除。
您絕對可以使用您所寫的解決方案。但是,在您需要 更改使用者數量?
不,你不能在鉤子內使用鉤子。它可能“有效”,但 React 告訴你它無法可靠地工作,並且你做錯了。必須在自訂鉤子頂層元件的頂層呼叫鉤子。
您的方向是正確的,但解決問題的方法是
div
元素上提供一些數據,以便讓您知道點擊了哪個使用者元素。它看起來像這樣: