0

I have the following two components.

<Foo>
  <Bars/>
<Foo>

When Foo is called the console shows:

call Bar useEffect
Warning: Cant perform a React state update on an unmounted component...
call Foo useEffect
call Bar useEffect again

Here's the codepen but it doesn't generate the same warning which could be because its in development mode on my local. It does show null prints though.

https://codepen.io/rsgmon/pen/OJmPGpa

Is this component structure, with useEffect in each component, not recommended/allowed?
If it's ok what do I need to change to avoid the warning?

rsgmon
  • 1,892
  • 4
  • 23
  • 35
  • Show some code? It sounds like you may not have a proper destructor (return value that cleans up) in the useEffect. - Example [here](https://stackoverflow.com/questions/56442582/react-hooks-cant-perform-a-react-state-update-on-an-unmounted-component) – Nikki9696 Jun 30 '21 at 17:06
  • @Nikki9696 Coded added and thanks for the suggested link. I did try the suggested fixes but still get the error. – rsgmon Jun 30 '21 at 17:44
  • I'm a little confused. I don't see Bars mounted? Like, there's no element in here, just a stringify. - never mind, I can read – Nikki9696 Jun 30 '21 at 18:07
  • Okay, I see your sample has Bars nested in Foo, but the Foo element is also appending Bars. I can't test this since you have references to some API though. I'm still slightly confused as I don't see the useEffect returning anything. If you can pop it up on a pen or something with a fake api, folks can debug it...? – Nikki9696 Jun 30 '21 at 18:10
  • @Nikki9696 https://codepen.io/rsgmon/pen/OJmPGpa Probably because I'm running in development mode on my local it shows the warning whereas on codepen it doesn't. Thanks for any assistance or insights. – rsgmon Jul 01 '21 at 03:28

1 Answers1

0

This is likely occurring because a state update to Foo triggers a re-render, causing Bars to unmount and remount.

Then the original Bars API request completes and it attempts to update state on the component that isn't mounted anymore, hence the warning.

You can fix it by declaring a variable inside the effect that's initially false and setting it to true in the effect's cleanup function:

useEffect(() => {
  let unmounted = false;
  
  doSomeAsynchronousStuff()
    .then( result => {

      if (unmounted) {
        return; // not mounted anymore. bail.
      }

      // do stuff with result

    })

  return () => unmounted = true; // cleanup gets called on un-mount
}, [])
ray
  • 26,557
  • 5
  • 28
  • 27
  • Thanks @ray-hatfield, adding your suggested code into Bars did it. I'll have to read about clean up on `useEffect` as I'm guessing `unmounted` isn't a special variable to useEffect. – rsgmon Jul 01 '21 at 13:59
  • There's nothing special about the name unmounted. Call it whatever you want. – ray Jul 01 '21 at 14:11