https://codesandbox.io/s/react-usecontextuseeffect-stale-data-bug-l81sn
在组件中,当某个值更改时,我使用useEffect
做某事。现在,它仅是一个简单计数器的值,但在现实世界中,它将是一个数组,其中要删除或添加项目等。
在useEffect
中,我还进行了大小调整检测。再次,在这个例子中不是很有趣。
const App = props => {
const [count, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}, 0);
return (
<CountContext.Provider value={{ count, dispatch }}>
<div className="App">
<h1>App</h1>
<Counter />
</div>
</CountContext.Provider>
);
};
const Counter = () => {
const counter = useContext(CountContext);
useEffect(() => {
window.addEventListener('resize', () => {
console.log(counter.count);
})
},[counter])
return (
<div className="Counter">
<p>Counter: {counter.count}</p>
<input
type="button"
value="+"
onClick={() => counter.dispatch({ type: 'INCREMENT' })}
/>
<input
type="button"
value="-"
onClick={() => counter.dispatch({ type: 'DECREMENT' })}
/>
</div>
);
};
问题在于,当我调整视口大小时,console.log(counter.count)
显示所有以前的值:
答案 0 :(得分:2)
问题是useEffect()方法中的内存泄漏。您需要清理重新渲染。我分叉了您的沙箱,并对此进行了测试,它可以按预期工作:
$tableName = $query->getModel()->getTable();
请注意返回清理代码并将代码重构为被调用函数,以便在卸除时可以正确将其删除。
答案 1 :(得分:1)
每次状态更改时,您都会添加一个新的eventListener。三个更改-三个eventListeners。此外,在卸载Counter组件时,侦听器会保持活动状态,从而导致内存泄漏。 首先,您可以在useEffect之外使用此部分:
window.addEventListener('resize', () => {
console.log(counter.count);
})
或者您应该使用空数组作为useEffect中的依赖项列表,然后它将仅触发一次:
useEffect(() => {
}, []) // empty array here says 'do it once'
最后,useEffect是获取数据或预订事件等的理想场所。但不要忘记在不再需要组件后将其清除。为此,请返回useEffect中的清洗功能:
useEffect(() => {
// your main logic here
...
// cleaning up function:
return () => {
removeEventListener, unsubscribe etc...
}
}, [])