javascript - 当将函数作为 props 传递时,Array.map 中的 React 函数组件总是会重新渲染

标签 javascript reactjs react-hooks react-functional-component

我试图在集中管理所有子状态的父组件中渲染多个按钮。这意味着父存储例如单击状态,每个按钮在其自己的状态下的禁用状态,使用 useState 并将其作为 props 传递给子级。此外,onClick 函数也在父组件内部定义,并传递给每个子组件。目前我正在这样做:

const [isSelected, setIsSelected] = useState(Array(49).fill(false));
...
const onClick = useCallback((index) => {
     const newIsSelected = [...prev];
     newIsSelected[i] = !newIsSelected[i];
     return newIsSelected;
}, []);
...

(In the render function:)

return isSelected.map((isFieldSelected, key) => {
     <React.Fragment key={key}>
          <TheChildComponent
               isSelected={isFieldSelected}
               onClick={onClick}
          />
     </React.Fragment/>
})

为了尝试阻止子组件重新渲染,我正在使用...

  • ... useCallback 使 React 看到 onClick 函数始终保持不变
  • ... React.Fragment 让 React 再次找到组件,否则子组件将不会有唯一的 id 或类似的东西

子组件导出为:

导出默认的React.memo(TheChildComponent,compareEquality)

 const compareEquality = (prev, next) => {
      console.log(prev, next);
      return prev.isSelected === next.isSelected;
 }

不知何故,compareEquality中的日志行永远不会被执行,因此我知道compareEquality永远不会被执行。我也不知道为什么会这样。

我已经检查了所有博客、之前的 Stackoverflow 问题等,但尚未找到一种方法来防止每次至少一个组件执行 onClick 函数时重新渲染子组件,并通过执行以下操作更新了 isSelected 状态。

如果有人能指出我正确的方向或解释我的问题出在哪里,我会非常高兴。

提前致谢!

最佳答案

这段代码实际上会在每次渲染时生成一个新的 onClick 函数,因为 useCallback 没有给出 deps 数组:

const onClick = useCallback((index) => {
     const newIsSelected = [...prev];
     newIsSelected[i] = !newIsSelected[i];
     return newIsSelected;
});

以下内容应该只创建一个 onClick 函数并在所有渲染中重复使用它:

const onClick = useCallback((index) => {
     const newIsSelected = [...prev];
     newIsSelected[i] = !newIsSelected[i];
     return newIsSelected;
}, []);

与普通的React.memo结合,这应该可以防止子项重新渲染,除非isSelected发生变化。 (您的 React.memo 的第二个参数应该也解决了这个问题 - 我不确定为什么这不起作用。)

顺便说一句,您可以简化此代码:

     <React.Fragment key={key}>
          <TheChildComponent
               isSelected={isFieldSelected}
               onClick={onClick}
          />
     </React.Fragment/>

以下内容:

          <TheChildComponent key={key}
               isSelected={isFieldSelected}
               onClick={onClick}
          />

(假设您确实只需要 map 主体中的一个组件)。

关于javascript - 当将函数作为 props 传递时,Array.map 中的 React 函数组件总是会重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68671725/

相关文章:

reactjs - 我如何使用 hook 中的 react-toastify?

javascript - 沙盒中的 Node.js

javascript - React 钩子(Hook)形式 - 对话框内的字段数组( Material UI)

c# - 将 "react js"构建到我的 "asp.net core web api"的 wwwroot 文件夹时的路由问题

reactjs - 使用 ref 作为 Material UI InputLabel

javascript - 如何连接 Prop

javascript - 异步回调 - 放置回调函数

javascript - 如何从子范围内的指令设置 Angular Controller 对象属性值

reactjs - 无法使用 React-Query + Graphql-Request 在 useQuery 中传递参数

reactjs - 如何避免使用useRef重新渲染 react ?