如何解决反应-过滤存储中的对象会导致递归/无限循环 选择器A 选择器B
我在我的React应用程序中使用redux存储来存储诸如费用之类的数据。
现在,我在这些组件之一中使用这些费用来计算要显示的TODO徽章计数
const [badgeValue,setBadgeValue] = useState(0);
const expenses = useSelector(({ expenses }: RootState) => expenses.items);
useEffect(() => {
const setBadge = async () => {
const badgeNumber = await calculateRequestBadgeNumber(expenses);
setBadgeValue(badgeNumber);
};
setBadge();
return () => setBadgeValue(0);
},[expenses]);
这按预期工作。现在,当我想像这样过滤掉已删除的费用时,我遇到了一个怪异的副作用:
const expenses = useSelector(({ expenses }: RootState) =>
expenses.items.filter((expense: Expense) => !expense.deleted)
);
这导致useEffects的无限循环。为什么会这样?
解决方法
与涉及React钩子的大多数事物一样,所涉及对象的标识(例如,用===
测试的对象)在这里很重要。当expenses
的身份与上次渲染不同时,将触发您的效果。
选择器A
此钩子返回Redux状态的items
属性的expenses
属性。如果状态不变,则items
属性的身份也不会改变。
const expenses = useSelector(({ expenses }: RootState) => expenses.items);
选择器B
这将返回在items数组上调用filter
的结果。 filter方法返回一个全新的数组。
const expenses = useSelector(({ expenses }: RootState) =>
expenses.items.filter((expense: Expense) => !expense.deleted)
);
您正在观察的是选择器B每次在组件渲染时都返回一个新值,因此效果触发得太频繁了。
现在-useSelector
can cache its return value,如果状态未更改,则重用,但如果传递给它的选择器函数的身份保持不变,则仅 。您可以通过在模块作用域(而不是组件)中命名选择器来确保这一点。
const filteredExpenses = ({ expenses }: RootState) =>
expenses.items.filter((expense: Expense) => !expense.deleted);
const MyComponent = () => {
const [badgeValue,setBadgeValue] = useState(0);
const expenses = useSelector(filteredExpenses);
useEffect(() => {
const setBadge = async () => {
const badgeNumber = await calculateRequestBadgeNumber(expenses);
setBadgeValue(badgeNumber);
};
setBadge();
return () => setBadgeValue(0);
},[expenses]);
return <StuffToRender />;
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。