Understanding query deduplication option merging and dynamic options #7056
-
I'm struggling to come up with the correct mental model for how Tanstack query handles merging options from multiple For deduplication, originally I was under the impression that only the options from the request that gets deduplicated to wins out (eg: the component that gets mounted first), but this is not the case as seen in const myEndpoint = () =>
new Promise((res) => setTimeout(res, 5000)).then(() => 'hello world');
function Child() {
useQuery({
queryKey: ['example'],
queryFn: myEndpoint,
staleTime: Infinity,
});
return <div>Child</div>;
}
function App() {
useQuery({
queryKey: ['example'],
queryFn: myEndpoint,
staleTime: 0,
});
return <Child />;
} The effective Dynamic OptionsMy mental model for thinking for dynamic options is: TanStack query only responds to option changes if that option would trigger a new request or it modifies the query's cache calculations Thus one should, where available, pass in functions that are able to read the latest state. This has been shaped by a couple examples: 1. updating retryDelay is ineffective Our query function will always log attempts that are 10 seconds apart. No matter how many times our button is pressed. However, refocusing the window causes a refetch and our new retryDelay is picked up. Why is this? const myFailingEndpoint = () => {
console.log(new Date());
return Promise.reject(new Error('oh no'));
}
function App() {
const [status, setStatus] = useState(false);
const client = useQueryClient();
useQuery({
queryKey: ['example'],
queryFn: myFailingEndpoint,
retryDelay: status ? 1000 : 10000,
});
return (
<button
onClick={() => {
setStatus(true);
client.cancelQueries({ queryKey: ['example'] });
client.invalidateQueries({ queryKey: ['example'] });
}}
>
Click me
</button>
);
} 2. updating staleTime is effective Showing react query can incorporate changes to const myEndpoint = () => {
console.log('executing');
return new Promise((res) => setTimeout(res, 10000)).then(() => 'hello world');
};
function App() {
const [status, setStatus] = useState(false);
useQuery({
queryKey: ['example'],
queryFn: myEndpoint,
staleTime: status ? Infinity : 0,
});
return (
<button
onClick={() => {
setStatus(true);
}}
>
Click me
</button>
);
} The devtools identify that our query is will be fresh after we click the button regardless of whether our request was in the fetching state when we pressed the button Bonus: how many times will our query function console log? Just once. Ignoring that inconsistent query options can be a bit of a code smell, is there documentation regarding query option behaviors when they are updated or deduplicated? What is the best mental model to have when reviewing when inconsistent query options are present? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 11 replies
-
that's wrong. options are always updated. Why wouldn't they? There is no "options deduplication" - only "request deduplication".
In this example,
Here, you don't do anything else in the second event handler, so your examples are not comparable. |
Beta Was this translation helpful? Give feedback.
issue: #3706
pr: #7081