如何解决当我使用选择器普通函数时,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
钩子 internally 的作用有关。
useSelector
运行您的选择器并检查结果是否与之前收到的结果相同(参考比较)。如果结果不同,则存储新结果并强制重新渲染。如果结果相同,则不会替换旧结果,也不会触发重新渲染。
这意味着每次 store 更新时,即使它是状态的不相关部分,也会运行您的复杂函数以确定结果是否已更改。就您而言,它总是一个新的参考,因此总是一个变化。
我认为处理这个问题的最好方法是让你的选择器尽可能简单,或者使用某种形式的更复杂的记忆,比如 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();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。