Heim  >  Fragen und Antworten  >  Hauptteil

Kann ich React.useCallback in einem anderen React.useCallback verwenden?

<p>有一个渲染用户卡片的组件</p> <p> <pre class="brush:js;toolbar:false;">import React from „react“; const User = React.memo(function({id, name, isSelected, ...other}) { zurückkehren ( <div {...andere}> {name} - {isSelected && "Ausgewählt"} </div> ); }); Standardbenutzer exportieren;</pre> </p> <p>以及渲染用户卡的父组件</p> <p> <pre class="brush:js;toolbar:false;">import React from „react“; Funktion 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); returnusers.map((user) => { const isSelected = selectedUserId === user.id; zurückkehren ( <Benutzer {...Benutzer} key={user.id} isSelected={isSelected} onClick={() => setSelectedUserId(user.id)} /> ); }); } Standardanwendung exportieren;</pre> </p> <p>任务是“选择用户后避免重新渲染其他用户卡“</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}) { zurückkehren ( <div {...andere}> {name} - {isSelected && "Ausgewählt"} </div> ); }); Funktion 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); }, []); returnusers.map((user) => { const isSelected = selectedUserId === user.id; zurückkehren ( <Benutzer {...Benutzer} key={user.id} isSelected={isSelected} onClick={handleSelectUser(user.id)} /> ); }); } Standardanwendung exportieren;</pre> </p> <p>In diesem Fall gibt <code>React.useCallback</code> eine anonyme Funktion</p> zurück <p><strong>Ergebnis: Alle Benutzerkarten werden nach jedem Klick immer noch neu gerendert</strong></p> <p>Ich habe beschlossen, diese anonyme Funktion in <code>React.useCallback</code></p> einzubinden. <p> <pre class="brush:js;toolbar:false;">import React from „react“; const User = React.memo(function({id, name, isSelected, ...other}) { zurückkehren ( <div {...andere}> {name} - {isSelected && </div> ); }); Funktion 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); }, []); }, []); returnusers.map((user) => { const isSelected = selectedUserId === user.id; zurückkehren ( <Benutzer {...Benutzer} key={user.id} isSelected={isSelected} onClick={handleSelectUser(user.id)} /> ); }); } Standardanwendung exportieren;</pre> </p> <p>Das Problem ist gelöst, aber es bleibt noch eine Frage: Habe ich es richtig gemacht? Das React-Team sagt: <em>Hooks nicht innerhalb von Schleifen, Bedingungen oder verschachtelten Funktionen aufrufen</em> Welche Nebenwirkungen bekomme ich? </p> <p>Hinweis: Berühren Sie nicht die Komponente <code>user</code></p>
P粉153503989P粉153503989437 Tage vor550

Antworte allen(1)Ich werde antworten

  • 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}
          />
        );
      });
    }

    Antwort
    0
  • StornierenAntwort