unmount组件不要忘记清空timeout和interval
2020年5月11日 • ... • ☕️ 1 min read
使用函数式组件,更新state的时候,碰到一个警告
意思是,在已经卸载的组件上,无法执行state更新,会造成内存泄漏。记得在useEffect的cleanup里取消所有订阅和异步任务。
举个例子
function Foo () {
const [bar, setBar] = useState(true);
useEffect(() => {
setBar(false);
setTimeout(() => {
setBar(true);
}, 1000);
}, []);
return (<div>123</div>);
};
function App() {
const [foo, setFoo] = useState(true);
return (
<div className="App" onClick={() => setFoo(false)}>
{foo && <Foo></Foo>}
</div>
);
}
原因和上次说的一样,useEffect存储的函数闭包存储了state,通过dispatchAction进行事件分发。由于setTimeout是个异步函数,setTimeout会脱离React的周期,调用到setBar的时候,Foo组件的状态已经不同步。
所以,要记得在组件卸载的时候清除这些异步函数(setTimeout/setInterval/Ajax等)。
useEffect(() => {
setBar(false);
const timer = setTimeout(() => {
setBar(true);
}, 1000);
return () => clearTimeout(timer);}, []);
如果timer是在useEffect外部定义的,还需要用useRef存储timer,然后在useEffect的返回函数里清除。