搜尋

首頁  >  問答  >  主體

我可以在另一個 React.useCallback 中使用 React.useCallback 嗎?

<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>
P粉153503989P粉153503989439 天前559

全部回覆(1)我來回復

  • P粉810050669

    P粉8100506692023-09-02 12:43:37

    解釋為什麼不能在鉤子內部調用鉤子(​​並期望它一致且可靠地工作)

    為什麼你不能在鉤子內部調用鉤子- 去這裡進行超深入的研究,其中的上下文比我在這個答案中需要提供的更多https://overreacted.io/why-do-hooks -rely-on-call-order/

    #您的解決方案之所以有效,是因為儘管“違反了規則”,但對掛鉤的調用順序始終相同......直到用戶被添加或從狀態中刪除。

    您絕對可以使用您所寫的解決方案。但是,在您需要 更改使用者數量


    不,你不能在鉤子內使用鉤子。它可能“有效”,但 React 告訴你它無法可靠地工作,並且你做錯了。必須在自訂鉤子頂層元件的頂層呼叫鉤子。

    您的方向是正確的,但解決問題的方法是

    1. 使用提供給回呼函數的參數作為被點擊元素的來源 AND
    2. 如果您無法修改 User 元件,則必須在 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);
    
      // this callback is referentially stable - it doesn't change between renders because it has no dependencies
      const handleSelectUser = React.useCallback((e) => {
        setSelectedUserId(+e.target.getAttribute('data-userid'));
      }, []);
    
      return users.map((user) => {
        const isSelected = selectedUserId === user.id;
    
        return (
          <User
            {...user}
            data-userid={user.id} <- this line
            key={user.id}
            isSelected={isSelected}
            onClick={handleSelectUser}
          />
        );
      });
    }

    回覆
    0
  • 取消回覆