`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•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•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-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•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-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•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']

afraid-scarletOP•3y ago
Ah, ok
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.