javascript - Array.map 中的 React 功能组件在将函数作为道具传递时总是重新渲染
问题描述
我正在尝试在集中管理所有子状态的父组件中呈现多个按钮。这意味着父级存储例如单击状态,每个按钮在他自己的状态下的禁用状态useState
,并将其作为道具传递给子级。此外,该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
让反应看到 onClick 功能始终保持不变 - ...
React.Fragment
让反应再次找到一个组件,因为否则孩子将没有唯一的ID或类似的东西
子组件导出为:
export default 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;
}, []);
结合 vanilla React.memo
,这应该可以防止孩子重新渲染,除非发生isSelected
变化。(你的第二个论点React.memo
应该也解决了这个问题——我不确定为什么这不起作用。)
作为旁注,您可以简化此代码:
<React.Fragment key={key}>
<TheChildComponent
isSelected={isFieldSelected}
onClick={onClick}
/>
</React.Fragment/>
到以下:
<TheChildComponent key={key}
isSelected={isFieldSelected}
onClick={onClick}
/>
(假设您确实只需要 的主体中的单个组件map
)。
推荐阅读
- python - 如何在命令提示符下从 Scrapy 的输出中删除 \r\n?
- python - 在 python 列表中对午餐项目进行排序
- java - 与后端 API 交互
- ruby-on-rails - 如何解决: SQLException: no such table: locations: ALTER TABLE "locations" ADD "user_id" integer
- python - 为什么调用 .clear() 后的 dict 大小为 72 字节,而实例化时为 240 字节?
- model - Prestashop 模型不从 lang 表中加载数据
- reactjs - FileManager 对话框内容区域中的 CKEditor 文本字段不起作用(替代文本、宽度、高度......)
- flutter - 如何在不重启应用的情况下更改 Flutter 应用语言?
- python - 使用交叉验证拟合 randomForest 模型
- javascript - 从 JSON 回显接收数据的 Javascript 错误