我有一个使用redux和hook的React无状态组件。我需要显示页面加载时的项目数(useEffect),并在每次添加或删除项目(store.subscribe)时进行更新
useEffect(() => {
setState({
items: store.getState().items.length
});
}, []);
store.subscribe(() => {
setState({
items: store.getState().items.length
});
});
但是这导致控制台显示警告无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。
如何从useEffect内部退订?
答案 0 :(得分:1)
从useEffect返回一个函数进行清理。因此,在卸载组件时将调用返回的函数。
store.subscribe
返回一个取消订阅的函数。使用useRef
钩子保存其引用,并从useEffect
钩子返回相同的引用。
在文档https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup中对其进行阅读。
const storeRef = useRef(() => {});
useEffect(() => {
storeRef.current = store.subscribe(() => {
setState({
items: store.getState().items.length
});
});
return storeRef.current;
}, []);
useEffect(() => {
setState({
items: store.getState().items.length
});
return storeRef.current;
}, []);
答案 1 :(得分:0)
如果将useEffect调用的第二个参数设置为[],则效果回调函数将充当ComponentDidMount。如果该回调函数返回一个函数,则该函数将在卸载组件(ComponentWillUnmount)之前被调用。
我猜这个setState应该用setItems替换,如下所示。 请尝试此代码。
const [items, setItems] = useState([]);
useEffect(() => {
setItems(store.getState().items.length);
const unsubscribe = store.subscribe(() => {
setItems(store.getState().items.length);
});
return unsubscribe;
}, []);
答案 2 :(得分:0)
一开始不应该直接使用商店。
如果您需要从存储中读取值作为组件的一部分,则应使用对您有用的React-Redux API:connect
和useSelector
。他们已经根据需要管理订阅和取消订阅商店的工作,因此您的组件可以仅指定它需要的数据。