我试图在集中管理所有子状态的父组件中渲染多个按钮。这意味着父存储例如单击状态,每个按钮在其自己的状态下的禁用状态,使用 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/