Clearing query data without invoking a fetch
I have a resource that returns a 404 when it hasn't been previously created.
A mutation is invoked, which creates the said resource - and the original query then runs and returns the object after invalidating the query.
Another mutation performs a DELETE. Because I know a refetch would return a 404 - I'd prefer to prevent useQuery from refetching the data.
I assumed that I could do something within the
onSuccess
on the mutation - but all options seem to lead to a re-fetch.
What am I missing? Do I need to also cancel the query after resetting perhaps?22 Replies
extended-yellow•2y ago
The query has a subscriber. What do you expect what happens if you delete the resource? Do you want to show the deleted resource or show an error?
conventional-tanOP•2y ago
In the case of undefined or no data, I show a prompt to the user allowing them to create it.
So really, I just want to fire the DELETE to my API, and have the cache cleared as if it had no data in it - without it re-requesting the data (since I know it would return a 404 in this case..).
FWIW - there's a different mutation that ADDS the data. And in this case it works fine, because I send the POST - then invalidate the query which in turn re-requests the data (and in this case, doesn't return a 404..).
extended-yellow•2y ago
Can you set the cache entry to be null?
absent-sapphire•2y ago
Yeah you can't have data be undefined in the cache, so I think you'd have to do
queryClient.setQueryData(queryKey, null)
conventional-tanOP•2y ago
Right, so - maybe set the initialDefault to null and set it to null. I'll give that a shot.
Ok - this was the solution. I defaulted the data to null.. and set the data to null, which doesn't invoke a fresh if not stale.
conscious-sapphire•2y ago
good that this solves it for you, I just don't fully understand the use-case. If you want to clear the cache without a refetch
queryClient.removeQueries
is what you want: It just removes data from the cache, nothing else.
Now your comment says:
This removes the entire query but doesn't cause a redraw.Yes, it doesn't. Because if it would re-render the component, the query would re-run, because a query that has no data starts to run the queryFn, just like if the component rendered for the first time. So it's pretty weird to remove cached data for a query that is currently rendered on screen, but don't want a refetch, but still want a re-render. That's kind of impossible 😅
conventional-tanOP•2y ago
Maybe I wasn't so great at explaining this.
All I really wanted was to run the mutation that deletes the object. Prior to making the request, the component was showing the data. After the delete, the component should update to reflect the lack of data.
However, I didn't want useQuery to re-query the object because it was already deleted. So I wanted some way to clear that data without it re-fetching.
In my rudementary test above, using removeQueries didn't cause the component to update to reflect the lack of data. setQueryData DID do this tho - once I'd updated to a null value.
I think perhaps there was a mis-understanding of removing cached data, vs setting it to some form of an empty value.
Your last statement is a bit confusing to me also. If you removed cache data, isn't that like an optimistic update? I.e. - you removed the data, why would the component not update to reflect that? Why can't I remove it - have the component update to reflect the lack of data, but not re-fetch?
conscious-sapphire•2y ago
After the delete, the component should update to reflect the lack of data.the best way to do that is probably to not render that component at all in that case. Unmount it after the delete mutation
extended-yellow•2y ago
Which status should the query be in then?
conscious-sapphire•2y ago
it's like being on
<User id={1} />
and then we delete user 1 from within that page. I won't continue to render that component, but redirect the user back to the user list or somewhere else ...conventional-tanOP•2y ago
Right, but that's a pretty opinionated approach right? In my case - I'm working with a (very) old API.. which admittedly doesn't help. So I was just trying to determine what the recommended approach was.
It seemed counter intuitive to me to have to completely unmount the component in this case.
(the delete happens in a dialog with the parent displaying the data.. ).
At the end of the day, for me - I just set the data to null now using setQueryData which works.
extended-yellow•2y ago
Query is an asynchronous state manager. Can’t have state without a server. If you don’t want to use the state, don’t use the useQuery
conventional-tanOP•2y ago
For context, this a a configuration object thats written via the API. It returns a 404 when you GET the object if it doesn't already exist - but when it does exist, it returns the object. There's no list involved.
Not sure I said there wasn't a server.. 🙂
Its just about saving an additional API call when I know its not needed.
extended-yellow•2y ago
Like Dominik said: move to a different component to not have an unnecessary useQuery.
conventional-tanOP•2y ago
Hrm, there's only one useQuery, with an associated mutation. But maybe this is all just my mis-understanding of how to properly use tanstack query.
conscious-sapphire•2y ago
it's fine to use setQueryData and set it to null. Query will be in success state with data: null; TypeScript won't like it much because types are usually tied to what the queryFn returned, but it'll work.
conventional-tanOP•2y ago
Yeah, the queryFn returns a null value with the 404 result.. I knew that was going to be a problem.
Are useQueries supposed to be used directly in the components? I have mine in an seperate ts module wrapped up in their own functions..
conscious-sapphire•2y ago
Are useQueries supposed to be used directly in the components?it's a hook, so in components or in a custom hook
conventional-tanOP•2y ago
Sure.. this a composable Vue project, so its created / in the setup function. The actual useQuery is an import from elsewhere tho, and called within the component.
I think thats prolly moot tho. I think what I'm doing probably makes sense for this particular API call.
ok, well - thanks for the help and advice.
manual-pink•14mo ago
@TkDodo 🔮 Hi and sorry for writting here but it's related; currently I want to clear the entire cache after user log out. I've tried using
client.clear()
or client.removeQueries()
but all of them refetch the active queries, is there I am missing?eastern-cyan•14mo ago
@Emiliano Bucci the reason why that might be happening is because by the time you're calling
client.clear
or client.removeQueries()
, you're still on the page (or even nested in the heirarchy) where query calls are being made. If you take a user to another page/screen first which doesn't deal with any query call, then your issue might be fixed.manual-pink•14mo ago
@areeb Hi and thanks for the answer; yes that's why, thanks!