unmount组件不要忘记清空timeout和interval

May 11, 2020 ... ☕️ 1 min read

使用函数式组件,更新state的时候,碰到一个警告

state-after-unmounted

意思是,在已经卸载的组件上,无法执行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的返回函数里清除。

#React#useState