1

I only use useEffect() in one place in my app as follows:

  useEffect(() => {
    document.body.addEventListener('click', bodyClicked);
    return () => {
      document.body.removeEventListener('click', bodyClicked);
    };
  }, [bodyClicked]);

  function bodyClicked() {
    dispatch({type: 'toggleMenuPageOff'});
  }

I am getting this warning:

react_devtools_backend.js:4061 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. at WEBPACK_DEFAULT_EXPORT (http://localhost:3000/bundle.js:4146:70) at div

Why is this a memory leak and how can I write it correctly to remove the warning?

favor
  • 355
  • 2
  • 13
  • That code looks fine. Are you sure the cause is a useEffect? The message does mention useEffect, but that's just because it's a common case. It is not the only way to set state after a component has unmounted. – Nicholas Tower Feb 22 '22 at 00:44
  • No, at best their answer is a performance optimization, not a fix for the warning. You do not have an infinite loop. The warning you're seeing can only happen when setting state. If the `dispatch` in the code you showed is redux's dispatch function, then these lines of code are not causing the warning. Look for things that are setting state after a delay, such as in a `setTimeout` or after `await`ing a promise. – Nicholas Tower Feb 22 '22 at 02:24
  • I was detecting location, which even when cached takes 2s to respond ... by then the component was not mounted ... Just need to update my GUI. – favor Mar 05 '22 at 23:05

2 Answers2

1

You're creating an infinite loop. the function you're if inside the components code is being recreated on each rerender which means it will trigger useEffect and therefore be called again and again...

https://reactjs.org/docs/hooks-reference.html#usecallback

  • What I mean is that the function is not recreated on each rerender. If you have something like: ... useEffect(() => { yourFunction(); }, [yourFunction]) const yourFunction = () => { dispatch("action"); } ... Function is being recreated over and over again for each rerender. And a change on this function (which will be triggered on the component rerender) will call useEffect again https://stackoverflow.com/questions/62601538/react-useeffect-passing-a-function-in-the-dependency-array/62601621 – Ricardo Ferreira Feb 22 '22 at 00:56
0

useEffect is regsitered with DOM and when the component is done running, then it is done running, your component is no longer in dom but browser is still listening to click event or in other words you are trying to perform click action after the component is unmounted this leads to memory leaks. Anything inside is useEffect is sideeffect and you gotta clean up the code to remove potential consequences

just inside of useeffect() add clean up code which is again a function that has return response of your useEffect() that actually clean up your code sideeffects

in your code you are using body clciked in your dependancies array keep that to [] empty

           useEffect(()=> {
              function bodyClicked(){
                 window.bodyclicked(.....)}
               return function(){
              window.removeeventlistener("click",bodyClicked)}
            }},[])
Nivethaa
  • 46
  • 3