How to cancel all subscriptions inside UseEffect in React

Tags: ,



I am getting this error – 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.

Here’s my useEffect hook, I used a ref called mounted to check if the component has unmounted or not but I am still getting the error when the component unmounts. (It takes about a minute for the error to show up).

    useEffect(() => {
            if(mounted.current){
                if(mincounter === 0 && hrcounter > 0){ 
                    setHrcounter(hrcounter - 1);
                    setMincounter(60);
                    mincounter > 0 && setTimeout(() => setMincounter(mincounter - 1) , 1000*60)
                }else if (mincounter === 0 && hrcounter === 0){
                    submitHandler()
                }else{
                    mincounter > 0 && setTimeout(() => setMincounter(mincounter - 1) , 1000*60)
                }
            }
        return () => {
            mounted.current = false
            console.log('info tab unmounting', mounted.current);
        }
    }, [mincounter, hrcounter, submitHandler,setHrcounter,setMincounter]);

TIA

Answer

   const [subscriptions, setSubscriptions] = useState([]);

I usually store all my subscriptions on my component state and then call them when component will be un mounted (in the cleanup of useEffect hook)

Like this:

   useEffect(() => {
      const subscription1 = ...
      const subscription2 = ...
      // When you create subscriptions, just store them on state
      setSubscriptions([...subscriptions, subscription1, subscription2]);

      // Cleanup (Detach subscriptions)
      return () => subscriptions.forEach(subscription => subscription)

   },[])


Source: stackoverflow