4

I have the below component , where i am displaying message for 5 sec and then removing it from home page.

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> 
        
        );
    };
2
  • Seems like Message component tries to update itself, but the component becomes unmounted. Post the code of what Message is doing? Commented Oct 10, 2020 at 13:26
  • yes, the message component is also used in other places. Commented Oct 10, 2020 at 13:29

2 Answers 2

7

Well, the error is actually quite self-explanatory: the state-changing function triggered by setTimeout is invoked after the component has already been unmounted. But it's no-op in disguise: component is no longer rendered, why should anyone be interested in its internal state changes?

Thankfully, React provides a documented way to clean up those and similar async state-changers - by using a function returned by an useEffect callback. 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).

Sign up to request clarification or add additional context in comments.

1 Comment

2

You get that warning as the timer you have setup might have been called after the component has been unmounted from the DOM.

You need to clear the timer in the cleanup callback from the useEffect hook:

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:

Why did we return a function from our effect? This is the optional cleanup mechanism for effects. Every effect may return a function that cleans up after it. 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 performs the cleanup when the component unmounts. 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. We’ll discuss why this helps avoid bugs and how to opt out of this behavior in case it creates performance issues later below.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.