-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
resetStore and refetchQueries can cause to refetch unmounted/inactive queries in StrictMode #11914
Comments
Here are my findings so far (no repro still -_-) I have a query on some page and it is set as "dirty" at some point apollo-client/src/core/QueryInfo.ts Lines 229 to 234 in d914d68
Then the query is unmounted, but remains "dirty" Later we call apollo-client/src/core/ApolloClient.ts Lines 594 to 603 in d914d68
In apollo-client/src/core/QueryManager.ts Line 969 in d914d68
In apollo-client/src/core/QueryManager.ts Lines 1072 to 1075 in d914d68
In apollo-client/src/core/QueryInfo.ts Lines 251 to 272 in d914d68
So it seems like at some point we should ignore "inactive" queries, aka I think the right place to do this check would be in apollo-client/src/core/QueryInfo.ts Lines 289 to 292 in d914d68
Otherwise, maybe we should NOT call |
Alright after going through this whole effort, I managed to make my minimal repro work!! |
@Cellule thanks for the bug report! The reproduction is super helpful! I've cloned your reproduction and started looking into this to understand myself. Its close to the weekend and I'm not sure I'll be able to finish until early next week, but thanks so much for your thorough analysis. This will definitely save me a ton of time. I'll get back to you as soon as I can! |
@Cellule looking at this further, your diagnosis seems correct. I had originally assumed there was a bug holding onto the I can now see that the only reason you're getting the refetch is because the I've updated your reproduction to show that once I've discussed this with the team to make sure adding a check for Thanks again for your thorough deep dive through the code and the time getting a reproduction! This made my life so much easier ❤️. |
@jerelmiller Great to hear! |
Haha right?!?! Thats why I was so confused why you were able to reproduce this because technically it shouldn't be possible 😆. From what I understand, its the fact that the If you want to test this at the React level with
If you opt for this approach, we have a handy apollo-client/src/react/hooks/__tests__/useQuery.test.tsx Lines 4177 to 4432 in 1a9c68a
If you want to test this with core APIs:
If you opt for this approach, we have a handy apollo-client/src/core/__tests__/ObservableQuery.ts Lines 2393 to 2509 in 1a9c68a
If you're struggling with either of these, let me know and I'd be happy to take a stab at creating a failing test for this to use as a base for implementing the change. |
So I'm not 100% sure why, but my current investigation leads me to this bit of code where apollo-client/src/react/hooks/useQuery.ts Lines 531 to 569 in 116723d
So in the end, it seems it's not an issue of query being cleaned up left in the QueryManager. It's a separate query that was never properly registered that is somehow in the list. |
That sounds very familiar to #11837 where I noticed something similar. Are you using React's strict mode by chance? I believe the the issue here was that the strict mode caused apollo-client/src/react/hooks/useQuery.ts Line 125 in 116723d
Take a look at the PR description in #11837. Perhaps you might be seeing something similar. Funny enough, the fix for that one was also doing a check for |
It does look like StrictMode is the offender in the repro above where However, I'm hitting this issue in production where StrictMode should do nothing. |
…resetting the store Closes apollographql#11914
My biggest fear is that there's a memory leak somehow. As for testing, I managed to write a test that fails without the fix and passes with it, it's not the cleanest approach, but let's discuss this on the PR directly |
Thanks for the PR! I'll take a look when I'm back on Monday. Have a great weekend! |
…resetting the store Closes apollographql#11914
…resetting the store Closes apollographql#11914
@jerelmiller const [mutation] = useMutation<ICreateAssetMutationResp, ICreateAssetMutationArgs>(
createAssetMutation,
{
ignoreResults: true,
refetchQueries: [
// needed because a sub-asset can be created at any level in the sub-assets page
// called if in /assets/:assetId/subs, to refresh the descendants count in treeView
"AssetParentTreeView",
// called if in /assets/:assetId, to refresh the descendants count in sub-asset tree-view
"AssetDetailsQuery",
],
}
) I went down through the code and ended up in |
I dug a bit more into it.
|
So clearly StrictMode is being a huge offender of this problem. apollo-client/src/react/hooks/useQuery.ts Lines 179 to 205 in 8047181
https://react.dev/reference/react/useState#caveats I'll try to come up with a better repro without StrictMode, but I do believe we should figure out and fix that issue in StrictMode as well to respect the rules of React |
@Cellule thanks for that confirmation. I suspected strict mode was the cause of at least one of the cases and agree we should try and do a better job here to avoid he double initialization. Do let me know if you're able to reproduce it without strict mode though. I'd be curious how that is allowed to happen, but my guess is the underlying cause is still very similar (e.g. multiple |
Now I'm starting to wonder if the main issue was fixed (aka dead queries in production) You probably have more context around that particular change, do you think this solved it ? |
@Cellule ok thats good news! That change was made to provide better compatibility with the new React Compiler. We were violating a few rules of React that would have made it difficult to integrate with it. Very possible the move away from the ref and into state helps here. |
Great, I updated the title of the issue to better represent the issue. |
Issue Description
We recently upgraded to version 3
Right now we use
resetStore
for a particular scenario.All graphql requests sent have an "organizationId" header associated.
Depending on that "organizationId" the user will see different content.
When the user changes to another organization we navigate to an almost empty page for the transition (to unmount all organization specific queries)
Then we call
resetStore
to refetch top-level queries that "might" be affected by the change of context.Once everything resolves, we navigate back to the normal app.
This used to work fine for the last 5 years, then we updated to apollo client version 3.
After some digging we found out that after calling
resetStore
some queries that are unmounted (confirmed 100%) end up being refetched.I debugged through the resetStore method, but I found no calls to refetch those queries.
So right now I have no idea what could cause those unmounted queries to be requested once again.
The biggest problem I have right now is that because those queries are called from the wrong context, it causes another mechanism to automatically redirect to the previous organization (so direct links work in any organization)
I have a lot of fail safe in place and it's fine 90% of the time, but when the network is slower those fail safe are not enough and it leads to the user no being able to change organization.
Any guidance on what could cause an unmounted query to hit the network once more after calling resetStore would be appreciated
Or tips on how to find out
Link to Reproduction
https://codesandbox.io/p/devbox/jolly-wilbur-n7m7jz?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clwtppgmj00073p6i6i7ie1cc%2522%252C%2522sizes%2522%253A%255B70%252C30%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clwtppgmj00023p6iumaf2w8i%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clwtppgmj00043p6igepxit5p%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clwtppgmj00063p6ixzewo28y%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B69.49598743432026%252C30.504012565679744%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clwtppgmj00023p6iumaf2w8i%2522%253A%257B%2522id%2522%253A%2522clwtppgmj00023p6iumaf2w8i%2522%252C%2522activeTabId%2522%253A%2522clwtpsi76003n3p6i7vuk56vl%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clwtppgmj00013p6ipicylgfm%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252FREADME.md%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%252C%257B%2522id%2522%253A%2522clwtpsi76003n3p6i7vuk56vl%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522initialSelections%2522%253A%255B%257B%2522startLineNumber%2522%253A25%252C%2522startColumn%2522%253A27%252C%2522endLineNumber%2522%253A25%252C%2522endColumn%2522%253A27%257D%255D%252C%2522filepath%2522%253A%2522%252Fsrc%252Flink.js%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%252C%257B%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252F.codesandbox%252Ftasks.json%2522%252C%2522id%2522%253A%2522clwumzut3002e3p6gxrqqie21%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%255D%257D%252C%2522clwtppgmj00063p6ixzewo28y%2522%253A%257B%2522id%2522%253A%2522clwtppgmj00063p6ixzewo28y%2522%252C%2522activeTabId%2522%253A%2522clxyzoh8p000l3j6jh401n3i3%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clwtppgmj00053p6iqkbdkq6f%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522TASK_PORT%2522%252C%2522taskId%2522%253A%2522start%2522%252C%2522port%2522%253A3000%252C%2522path%2522%253A%2522%252F%2522%257D%252C%257B%2522type%2522%253A%2522SETUP_TASKS%2522%252C%2522id%2522%253A%2522clxyzmn6r000o3j6jbsttjmyy%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%252C%257B%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A2222%252C%2522id%2522%253A%2522clxyzn4b5001p3j6jw7ckv2w6%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%252C%257B%2522type%2522%253A%2522TASK_PORT%2522%252C%2522port%2522%253A3000%252C%2522taskId%2522%253A%2522start%2522%252C%2522id%2522%253A%2522clxyzoh8p000l3j6jh401n3i3%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%255D%257D%252C%2522clwtppgmj00043p6igepxit5p%2522%253A%257B%2522id%2522%253A%2522clwtppgmj00043p6igepxit5p%2522%252C%2522activeTabId%2522%253A%2522clwtppgmj00033p6iw9cgtvcz%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clwtppgmj00033p6iw9cgtvcz%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522TASK_LOG%2522%252C%2522taskId%2522%253A%2522start%2522%257D%252C%257B%2522id%2522%253A%2522clwtqf2io00a13p6m5m1c3s1n%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522TERMINAL%2522%252C%2522shellId%2522%253A%2522clwtqf2lx0074dke2ga51ahaj%2522%257D%255D%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Atrue%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D
Reproduction Steps
@apollo/client
version3.10.4
The text was updated successfully, but these errors were encountered: