T
TanStack8mo ago
adverse-sapphire

What is the correct way to subscribe to a fresh queryObserver?

I skimmed the source for query observer and useBaseQuery and it's not obvious why the naive solution here isn't okay if our goal is that handleResult get notifications for current state + all future updates:
export function safeSubscribeObserver<Obs extends QueryObserver<any, any, any, any, any>>(
observer: Obs,
handleResult: Parameters<Obs['subscribe']>[0]
): () => void {
handleResult(observer.getCurrentResult());
const unsub = observer.subscribe(handleResult);
return unsub;
}
export function safeSubscribeObserver<Obs extends QueryObserver<any, any, any, any, any>>(
observer: Obs,
handleResult: Parameters<Obs['subscribe']>[0]
): () => void {
handleResult(observer.getCurrentResult());
const unsub = observer.subscribe(handleResult);
return unsub;
}
Vs what useBaseQuery seems to be doing:
export function safeSubscribeObserver<Obs extends QueryObserver<any, any, any, any, any>>(
observer: Obs,
handleResult: Parameters<Obs['subscribe']>[0]
): () => void {
handleResult(observer.getOptimisticResult(options));
const unsub = observer.subscribe(handleResult);
observer.updateResult();
return unsub;
}
export function safeSubscribeObserver<Obs extends QueryObserver<any, any, any, any, any>>(
observer: Obs,
handleResult: Parameters<Obs['subscribe']>[0]
): () => void {
handleResult(observer.getOptimisticResult(options));
const unsub = observer.subscribe(handleResult);
observer.updateResult();
return unsub;
}
Is the baseQuery implementation just working around react things or is it somehow more correct than the naive version? Note i know for certain that the query observer was just created but I don't know about if refetchOnMount is true or if the query key is in the cache or not. I also know the query key and options haven't changed. Seems like the only risk is that #currentResult is undefined still but that seems impossible given my other assumptions and reading of the code.
3 Replies
vicious-gold
vicious-gold8mo ago
I have no idea what you're talking about, sorry 😅🤷‍♂️
adverse-sapphire
adverse-sapphireOP8mo ago
I want a function to get called with the current value of a new query observer and all subsequent values the way useBaseQuery does this is here: https://github.com/TanStack/query/blob/main/packages/react-query/src/useBaseQuery.ts#L94 I have done a similar thing in the second code snippet I pasted above a more naive approach is to call with current value immediately after construction then subscribe is there some issue i'm missing? why do getOptimisticResult() then subscribe then updateResult() rather than just getCurrentResult() then subscribe is useBaseQuery using optimistic result to account for options changing or currentResult sometimes being undefined or out of date for some reason
vicious-gold
vicious-gold8mo ago
optimistic results accounts for things that are "going to happen" in the next effect; so when the query will fetch, it goes into a fetching state optimstically to avoid double-renders. but what are you trying to achieve? This is all very low level and as a consumer, you should just useQuery(...)

Did you find this page helpful?