javascript - 当我使用选择器正常功能时,ReactJs 状态正在循环中触发
问题描述
主要问题:我尝试在选择器中使用一个函数来重新构造数据并加入另一个变量,在这种情况下,我的组和他们的孩子作为项目放在一起,问题是每次都会在无限循环中调用该函数,尽管状态没有被改变。
我有这个选择器:
const groups = useSelector(state => selectProductGroups(state));
功能是这样的:
const groups = state.PlatformsReducer.groups;
const items = state.PlatformsReducer.items;
return groups.reduce((ac, g) => {
g.items = items.filter(i => i.groupId == g.productNumber);
if (ac[g.platformId]) {
ac[g.platformId].push(g);
} else {
ac[g.platformId] = [g];
}
return ac;
}, {});
};
So when I use a useEffect to detect if the groups variable has changed the useEffect is triggered in a loop despite the variable groups still empty.
Do you know why? or How to prevent this.
I now the problem is the function in the selector, but I don't know how to prevent this case.
解决方案
这与useSelector
钩子在内部的作用有关。
useSelector
运行您的选择器并检查结果是否与先前收到的结果相同(参考比较)。如果结果不同,则存储新结果并强制重新渲染。如果结果相同,则不会替换旧结果,也不会触发重新渲染。
这确实意味着每次存储更新时,即使它是状态的不相关部分,也会运行您的复杂函数来确定结果是否发生了变化。在你的情况下,它总是一个新的参考,因此总是一个变化。
我认为处理这个问题的最好方法是让你的选择器尽可能简单,或者使用某种形式的更复杂的记忆,比如 reselect 提供的。
下面是一个示例,说明您如何能够使选择器保持简单,但仍然可以使用自定义挂钩实现一种简单的方法来重用您的产品组选择。
const useProductGroups = () => {
// Get groups from the store.
// As the selector does not create a new object it should only
// trigger a rerender when groups changes in the store.
const groups = useSelector(state => state.PlatformsReducer.groups);
// Get items from the store,
// As the selector does not create a new object it should only
// trigger a rerender when items changes in the store.
const items = useSelector(state => state.PlatformsReducer.items);
// Reduce the group collection as desired inside of a useMemo
// so that the reduction only occurs when either items or groups
// changes.
const productGroups = useMemo(() => {
return groups.reduce((ac, g) => {
g.items = items.filter(i => i.groupId == g.productNumber);
if (ac[g.platformId]) {
ac[g.platformId].push(g);
} else {
ac[g.platformId] = [g];
}
return ac;
}, {});
}, [groups, items] /* dependency array on items / groups */);
// return the calculated product groups
return productGroups;
}
然后,您可以在函数组件中使用自定义挂钩:
const groups = useProductGroups();
推荐阅读
- javascript - 需要修复基于 vue js 的加密图表中损坏的图标
- excel - 如何使用 VBA 将数组公式插入到 Excel 中
- javascript - 在javascript / es6中比较嵌套对象后如何循环嵌套对象并推送字段
- mysql - 如何在 Laravel eloquent 中创建模型关系列表?
- javascript - ColdFusion 11:如何在不重新加载页面的情况下检查是否在 Struct 对象中找到表单字段值?
- python - 选择组合框并在另一个组合框 Tkinter 中显示值
- android - 2020 年 Android 中的 RCS 权限仍然是签名级别吗?(三星/谷歌)
- regex - 为什么 Perl 正则表达式 \K 不排除 \K 之前匹配的模式?
- mysql - 如果点与它相交,请指定位置名称 MySQL
- php - 正则表达式:在一个词组中捕获多个实例