简体   繁体   English

反应 setTimeout - memory 泄漏

[英]React setTimeout - memory leak

I have the below component, where i am displaying message for 5 sec and then removing it from home page.我有以下组件,我在其中显示消息 5 秒,然后将其从主页中删除。

when i switch between the pages, i'm getting below error sometimes.当我在页面之间切换时,有时会出现以下错误。 Any Advice please任何建议请

    index.js:1 Warning: Can't perform a React state update on an unmounted component. 
This is a no-op, but it indicates a memory leak in your application. 
To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

Code:代码:

 const Home = props => {
    
      const [visible, setVisible] = useState(true);
    
       useEffect(() => {
        setTimeout(() => setVisible(false), 5000);
      }, []); 
    
      return (
       <div >
         {visible && <Message showDefault={false}  /> }
         <BaseView  />
    
       </div> 
        
        );
    };

Well, the error is actually quite self-explanatory: the state-changing function triggered by setTimeout is invoked after the component has already been unmounted.好吧,这个错误实际上是不言自明的:在组件已经被卸载后调用由setTimeout触发的状态改变 function。 But it's no-op in disguise: component is no longer rendered, why should anyone be interested in its internal state changes?但它是变相的空操作:组件不再被渲染,为什么有人会对它的内部 state 变化感兴趣?

Thankfully, React provides a documented way to clean up those and similar async state-changers - by using a function returned by an useEffect callback.值得庆幸的是,React 提供了一种记录在案的方法来清理这些和类似的异步状态更改器——通过使用useEffect回调返回的 function。 Like this:像这样:

useEffect(() => {
  const timeoutId = setTimeout(() => setVisible(false), 5000);
  return function cleanup() {
    clearTimeout(timeoutId);
  }
}, []);

Note that the function doesn't have to be named (but it simplifies reading a bit).请注意,不必命名 function(但它可以简化阅读)。

You get that warning as the timer you have setup might have been called after the component has been unmounted from the DOM.您会收到该警告,因为您设置的计时器可能在组件从 DOM 卸载后被调用。

You need to clear the timer in the cleanup callback from the useEffect hook:您需要在useEffect挂钩的清理回调中清除计时器:

const Home = props => {
        
   const [visible, setVisible] = useState(true);
        
   useEffect(() => {
     const timerId = setTimeout(() => setVisible(false), 5000);
     //Use the clean up callback which would be executed weh the component is unmounted
     return () => clearTimeout(timerId);
   }, []); 
      
   return (
     <div >
       {visible && <Message showDefault={false}  /> }
       <BaseView/>
    </div> 
   );
};

From the React docs :来自React 文档

Why did we return a function from our effect?为什么我们从效果中返回 function? This is the optional cleanup mechanism for effects.这是效果的可选清理机制。 Every effect may return a function that cleans up after it.每个效果都可能返回一个 function,它会在它之后进行清理。 This lets us keep the logic for adding and removing subscriptions close to each other.这让我们可以让添加和删除订阅的逻辑彼此靠近。 They're part of the same effect!它们是相同效果的一部分!

When exactly does React clean up an effect? React 到底什么时候清理效果? React performs the cleanup when the component unmounts. React 在组件卸载时执行清理。 However, as we learned earlier, effects run for every render and not just once.然而,正如我们之前了解到的,效果会在每次渲染时运行,而不仅仅是一次。 This is why React also cleans up effects from the previous render before running the effects next time.这就是为什么 React 还会在下次运行效果之前清理上一次渲染的效果。 We'll discuss why this helps avoid bugs and how to opt out of this behavior in case it creates performance issues later below.我们将在下面讨论为什么这有助于避免错误以及如何选择退出此行为以防它造成性能问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM