T
TanStack•3y ago
afraid-scarlet

`staleTime` option prevents optimistic update from rerendering component

TL;DR is, when using Slatejs, and the onChange calls someMutation.mutate(), a useQuery hook won't pull in optimistic cache changes made to the cache in the onMutate function of useMutate when a queries' stale time is not 0. This only seems to manifest itself when the onChange is being triggered by SlateJS, as a regular input doesn't seem to have the same issues. Codesandbox reproduction: https://codesandbox.io/p/sandbox/slate-react-query-staletime-bug-fl4s2w?file=%2Fsrc%2Findex.tsx%3A98%2C1 Reproduction steps: In the example above, enter any character into the text field. The result line should display whatever your input is + "optimistic", but does not update Looking at the cached value in the devtools, the optimistic value is stored in the cache, but not reflected in the UI After the mutation resolves, the mutation value will cause the ui to update as expected. Potential resolutions: Removing the second argument here ({ listeners: false }) fixes the issue, but I'm not sure what repercussions that'll make. https://github.com/TanStack/query/blob/b18426da86e2b8990e8f4e7398baaf041f77ad19/packages/react-query/src/useBaseQuery.ts#L100 Not specifying a staleTime on the query client. Wrapping either the setSlateValue call or the exampleMutation.mutate call in a setTimeout with no delay works as expected.
Slate + React Query staleTime bug
CodeSandbox is an online editor tailored for web applications.
GitHub
query/packages/react-query/src/useBaseQuery.ts at b18426da86e2b8990...
🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query. - TanStack/query
8 Replies
harsh-harlequin
harsh-harlequin•3y ago
seems to be a timing issue with that slate editor. I've replaced it with a normal input, and added query cancellation (otherwise, the queryFn would overwrite the optimistic update) and it works fine: https://codesandbox.io/p/sandbox/slate-react-query-staletime-bug-forked-8rx6z6?file=%2Fsrc%2Findex.tsx%3A49%2C56
Slate + React Query staleTime bug (forked)
CodeSandbox is an online editor tailored for web applications.
harsh-harlequin
harsh-harlequin•3y ago
I've debugged this a bit and it seems like by the time the mutation runs, your query is already created from useQuery, but there are no observers yet (this happens with useSyncExternalStore). So the optimistic update writes to the cache, but it informs no observers, because there are none. I don't know what react-slate does in that onChange handler that a normal input does not do ..
afraid-scarlet
afraid-scarletOP•3y ago
I appreciate you looking into it! I'll have to do some investigation into the react-slate source to see if I can figure out what's up there. When you say "...there are no observers yet (this happens with useSyncExternalStore)", do you mean that useSyncExternalStore sets up the subscription when it runs? I may be looking at the useBaseQuery source incorrectly, but it seems that the observer is only set up on the first time that the useQuery hook is mounted, and then the options for it are updated when the options change (ie, the query key changes). If that's the case, then shouldn't the query observer have already been set up with the initial query key, and then just updating what the observer is subscribed to whenever the query key changes? It's also particularly interesting that the issue only occurs when staleTime is non-zero. So if all else fails, I can do some digging from there, too. I have to work on some other things this morning, but if time allows, I'll try and loop back and do some more debugging later in the day, or next week sometime.
harsh-harlequin
harsh-harlequin•3y ago
observer is created once, but the subscription to the Query itself happens in uSES. I've inspected query.observers and it's empty when the setQueryData from onMutate runs
It's also particularly interesting that the issue only occurs when staleTime is non-zero.
with staleTime: 0 you probably just see a background refetch somewhere, maybe because of window focus
afraid-scarlet
afraid-scarletOP•3y ago
Interesting. Definitely an area for more poking, then 🤔 Ah, the staleTime: 0 and background fetching makes sense. I just tested that, and it seems to be the case 👌 I may be doing something incorrectly in my code, but in the repro, I've updated it to log the query's subscriber count in the onMutate, and it's indicating that there's a subscriber by the time that onMutate fires. Maybe that's a different observer than you are talking about? Also slapped a console.log into the uSES where it subscribes, and that's running before any mutations happen, so I'm not sure how there couldn't be a subscriber?
harsh-harlequin
harsh-harlequin•3y ago
the subscriber is the old one. I've added a breakpoint. I entered an x after hi, so the text is now hix. but what we are seeing is that ['example', 'hi'] is being observerd (it's also the active query in the devtools), not ['example', 'hix']
No description
afraid-scarlet
afraid-scarletOP•3y ago
Ah, ok
afraid-scarlet
afraid-scarletOP•3y ago
Alright, so the issue seems to be less with Slate, and more with any time an input event isn't going through React. Here's a fork of the original example where I use an html input, but add an event listener to the dom node instead of using the onChange prop, and it has the same issue https://codesandbox.io/p/sandbox/slate-react-query-staletime-bug-forked-5rrnxt?file=%2Fsrc%2Findex.tsx%3A25%2C3
Slate + React Query staleTime bug (forked)
CodeSandbox is an online editor tailored for web applications.

Did you find this page helpful?