-
Notifications
You must be signed in to change notification settings - Fork 786
React 16.13.0 'Warning: Cannot update a component from inside the function body of a different component.' #3863
Comments
This issue might help you. |
@DamianBusz @bogdibota I spent a lot of time trying to create a narrow reproduction case, and did so here:
That demo does not use "useEffect" or "setState" at all, the only effect it calls is Apollo's "useQuery". As I mention in the README.md, there are a number of ways to making the warnings disappear, but it doesn't explain why they're happening. IMO this looks like something within @apollo/react-hooks that needs to be addressed. |
Same here. The only effect i am use is |
@dannycochran thanks for the hard work to reproduce the issue!! I have forked you repo and managed to isolate the issue a little further: https://github.com/bogdibota/usequery I have documented in the README more ways to make the warning go away and i've concluded the following: this seems to be caused by a component A updating the cache and another component B that listens to the same query as component A gets updated during the rendering phase. I think the reason that, in my example, you don't always get an error with 2 components is because, somehow, the query response is received and handled in the 'correct' order. |
@bogdibota confirmed I see the error pretty consistently in your repro, thanks for narrowing it down further. |
Same issue here. Thanks for narrowing it down. It does seem to be that querying the cache locally is somehow causing this. For context, I'm writing to the cache a I tried the 4 options in @bogdibota but none of them work so far. |
I just noticed this error in an application that is not using hooks but the components API. I am not sure if that makes a difference since the components are using the hooks under the hood. I followed Dan Abramov's recommendation to track down the culprit. The last line being called before handing over to react is private startQuerySubscription() {
...
// Make sure we're not attempting to re-render similar results
if (
previousResult &&
previousResult.loading === loading &&
previousResult.networkStatus === networkStatus &&
isEqual(previousResult.data, data)
) {
return;
}
this.forceUpdate();
^^^^^^^^^^^^^^^^^^^
},
error: error => {
... My guess is that the |
An investigation of an issue we have yielded similar results. That
I guess the observable is the confusing part, because it can sometimes run |
I am also getting this error, mainly when I have two components, both of which execute the same query, and one comes back before the other. |
in 16.13.1 seems it has become smth like:
both components make use of the same |
@pawelkleczek we're working on this. |
For me this happens when I pass Example code:
So, for a lack of a solution for refetching, I just call |
@bzhr the problem is, that you are calling refetch during render (of Parent). As you can imagine, refetch could set a bunch of states in different components at different levels (all components that subscribe to this query) so this must not be called during render. Those side effects were always supposed to be called in a useEffect(); |
@andreasgruenh Thank you for your answer. I'm still not sure what's the proper way to handle the state update. Should I use Thanks |
Your intention is to initiate the refetch on the button click. Side effects are very much allowed in event handlers. The only restriction is, that they should not be called during the call of your component function ("during render").
This way your components are being rendered without side effects. Only when a user clicks a button, the refetch function is called (which sets some states inside of apollo). |
Fixed in #3902, and released in React Apollo 3.1.4. Thanks all! |
@hwillson the issue is still reproducible in our test repo when you upgrade to 3.1.4: However, the warning message is slightly more informative: Warning: Cannot update a component (`InnerComponent`) while rendering a different component (`InnerComponent`). To locate the bad setState() call inside `InnerComponent`, follow the stack trace as described in https://fb.me/setstate-in-render
in InnerComponent (at src/index.tsx:42)
in WrapperComponent (at src/index.tsx:53)
in ApolloProvider (at src/index.tsx:47) |
Thanks all - investigating now. |
@cmakohon @dannycochran 3.1.5 has been released and should fully address this. Let me know if you're still noticing issues. Thanks! |
Thanks a lot. This works for me. Confirming with CI now 😄. @Chedvaka maybe try to make sure that you resolve to the right version via |
@tdeekens this is the output for yarn why @apollo/react-hooks: seems like the correct version is installed but I'm still getting the issue. |
Ok. Then I don't know why you're seing the error and if it's related to apollo itself. Also cause your stack trace doesn't have apollo at the top but your user context provider. |
@hwillson Thanks! Could you release the patch for |
I believe I'm having this same issue on |
Intended outcome:
After updating to React 16.13.0,
useQuery
should not throw unintentional state changes warning.Actual outcome:
After updating to React 16.13.0, in dev mode, every component that uses
useQuery
withoutskip: true
will throw this new warning.Warning: Cannot update a component from inside the function body of a different component.
More info about this warning can be found in the React changelog.
The actual functionality appears to be the same, from what I can tell.
How to reproduce the issue:
Update your React version to
16.13.0
where this warning was introduced and it will appear in the console once for each component usinguseQuery
withoutskip: true
.Version
Update 05.03:
react-apollo-network-status
for a global loading indicator. This loading indicator was updated by all the components that had auseQuery
hook (as expected)The text was updated successfully, but these errors were encountered: