T
TanStack3y ago
correct-apricot

Mutation with refetch

Hey, I am having a ListDisplay on my Frontend which fetches an array. After I mutate that array like deleting one object, it should show the new array in this ListDisplay…How can I force a refetch after a mutation?
27 Replies
absent-sapphire
absent-sapphire3y ago
Invalidations from Mutations | TanStack Query Docs
Invalidating queries is only half the battle. Knowing when to invalidate them is the other half. Usually when a mutation in your app succeeds, it's VERY likely that there are related queries in your application that need to be invalidated and possibly refetched to account for the new changes from your mutation. For example, assume we have a mu...
correct-apricot
correct-apricotOP3y ago
const mutateTwitch = useMutation({
mutationFn: (data: SocialType) => insertOrUpdateTwitchChannel(props.currentServer.id, data),
onSuccess: () => queryClient.invalidateQueries({queryKey: ["twitch-notification"]})
})
const mutateTwitch = useMutation({
mutationFn: (data: SocialType) => insertOrUpdateTwitchChannel(props.currentServer.id, data),
onSuccess: () => queryClient.invalidateQueries({queryKey: ["twitch-notification"]})
})
const {data, isLoading} = useQuery('twitch-notification', () => fetchTwitchChannel(serverId ?? "0"))
const {data, isLoading} = useQuery('twitch-notification', () => fetchTwitchChannel(serverId ?? "0"))
This still does not refetch somehow I need to reload the site to see the changes...Shouldnt it refetch everything and then rerender?
absent-sapphire
absent-sapphire3y ago
queryKeys need to be arrays, so this is wrong:
- useQuery('twitch-notification'
- +useQuery(['twitch-notification']
- useQuery('twitch-notification'
- +useQuery(['twitch-notification']
also, prefer the object syntax:
const {data, isLoading} = useQuery({
queryKey: ['twitch-notification'],
queryFn: () => fetchTwitchChannel(serverId ?? "0")
})
const {data, isLoading} = useQuery({
queryKey: ['twitch-notification'],
queryFn: () => fetchTwitchChannel(serverId ?? "0")
})
correct-apricot
correct-apricotOP3y ago
Ok thx👍🏼 I am going to try that tomorrow Still does not refetch somehow I now added this and it still does not refetch https://hastebin.skyra.pw/uholeveruq.ts This is my full code currently
absent-sapphire
absent-sapphire3y ago
please boil it down to a minimal reproduction on codesandbox
correct-apricot
correct-apricotOP3y ago
Okay Which api for fetching could I use? Cause mine is not online
absent-sapphire
absent-sapphire3y ago
Promise.resolve does the job just fine
correct-apricot
correct-apricotOP3y ago
ah ok So just add a PromiseResolve instead of insertOrUpdateTwitchChannel() ? Ah wait! So I added to my insert function a console.log....its getting called! So it is indeed refetching! But why doesnt anything change? Okay I got the problem My Backend is responding with the old data...Probably it is too fast requesting the data...What could I do to fix this? I delete something and my spring backend responds with two elements even I just deleted one I see that the onSuccess is called before it mutated something...My Backend received the refetch and then the delete
2023-10-21 18:33:38.213 DEBUG 3553 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Secured GET /api/discord/embed-manager/
2023-10-21 18:33:38.213 DEBUG 3553 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Secured GET /api/discord/embed-manager/
2023-10-21 18:33:38.615 DEBUG 3553 --- [nio-8080-exec-3] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
2023-10-21 18:33:38.615 DEBUG 3553 --- [nio-8080-exec-3] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
According to console.log it first mutates and then refetches.......But I see what my backend firstly receives
absent-sapphire
absent-sapphire3y ago
Your backend returns too early. It needs to "await" until the mutation actually finished
correct-apricot
correct-apricotOP3y ago
But it receives the delete after the refetch Thats wierd Let me check this
absent-sapphire
absent-sapphire3y ago
The get request could also be a window focus refetch ... it's really hard to say without seeing a repo but I'm almost 100% sure that RQ works fine in this scenario and the problem is somewhere else
correct-apricot
correct-apricotOP3y ago
I think it cannot be the window focus refetch because I dont leave the chrome window...I am checking the logs on the left and it deletes and then refetches at the same time the frontend sends it. Or could a window focus refetch still happen if I dont leave the window? I read the docs and it should only run the onSuccess if the delete was completed…Maby it is a problem from my Frontend
correct-apricot
correct-apricotOP3y ago
Aha...it now creates after the refetch...Maby react query does run the onSuccess instantly....Is React query compatible with ky?
No description
correct-apricot
correct-apricotOP3y ago
Because this is how my method for deleting looks like
export async function deleteEmbed(serverId: string, uuid: string) {
return api.delete(`${ORIGIN}/embed-manager/`, {
headers: {
'X-Server': serverId,
'X-UUID': uuid
}
}).formData
}
export async function deleteEmbed(serverId: string, uuid: string) {
return api.delete(`${ORIGIN}/embed-manager/`, {
headers: {
'X-Server': serverId,
'X-UUID': uuid
}
}).formData
}
Maby its not receiving the right responses
absent-sapphire
absent-sapphire3y ago
Maby react query does run the onSuccess instantly.
it does not
Is React query compatible with ky?
yes because it doesn't matter what produces the promise
correct-apricot
correct-apricotOP3y ago
Hmm Because it does send a refetch when the delete didn’t respond yet When does it run onSuccess? Even if it receives an error? Cause my backend returns 404 cause I removed the endpoint and it received a 200 for fetching and a 404 for deleting
correct-apricot
correct-apricotOP3y ago
Tbh a 404 for the mutation after the 200 (refetch)..
No description
absent-sapphire
absent-sapphire3y ago
When does it run onSuccess?
After the mutationFn returns a resolved promise
correct-apricot
correct-apricotOP3y ago
Is there any way it returns the promise even when it didn’t respond yet? Cause the backend received both requests at the same time I am going to artificially delay the response in the mutation and then I can see if something is not working correctly Yep I just delayed the response by 5s….Still onSuccess is being executed even my server did not respond! It instantly runs onSuccess Wait…I’ve got React Query in my Project….Not tanstack/react-query Could that be an issue? My react query ist v3 @TkDodo 🔮 I just saw that React Query 4 and 5 are even other packages on npm.com…..Could this be a problem? I still have 3
absent-sapphire
absent-sapphire3y ago
no. feel free to update but react-query has always executed onSuccess after the mutationFn. You can easily verify this with something like this:
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms))

useMutation({
mutationFn: async () => {
console.log('before request')
// simulate request that takes 1s
await sleep(1000)
console.log('after request)
return "some-data"
}
onSuccess: () => {
console.log('onSuccess')
}
})
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms))

useMutation({
mutationFn: async () => {
console.log('before request')
// simulate request that takes 1s
await sleep(1000)
console.log('after request)
return "some-data"
}
onSuccess: () => {
console.log('onSuccess')
}
})
Just replace your mutation with that and you should see the order of things clearly. So your problem is somewhere else and unless you're showing a minimal codesandbox, there's nothing I can do because sorry, it's a waste of my time.
correct-apricot
correct-apricotOP3y ago
killingsausage
CodeSandbox
dreamy-buck-gysp6s - CodeSandbox
dreamy-buck-gysp6s by killingsausage using ky, loader-utils, react, react-dom, react-query, react-scripts
correct-apricot
correct-apricotOP3y ago
This is my code...I am sorry I somehow dont get it managed to fix all those errors...Some things somehow dont work on this....There you can see everything from the QueryService and How I fetch the data and mutate it. I dont really now how I build it so you can test it but this is basically everything I did...Of course I changed some things to : any instead of all the types and so on but this shouldnt break anything. Tell me if you need something. Thanks again for your time Tk? @TkDodo 🔮 do you need more stuff?
absent-sapphire
absent-sapphire3y ago
I'm not looking into this until you show a small reproduction. the queryService is empty. There's tons of glue code, everything is red. Sorry, I already said that you should replace your actual fetching with a promise.resolve and you'll see that it works. I can't spend my time on this anymore, sorry
correct-apricot
correct-apricotOP3y ago
okay let me try this again.... bruh queryservice is indeed empty
correct-apricot
correct-apricotOP3y ago
@TkDodo 🔮 https://codesandbox.io/s/dreamy-buck-gysp6s Now it should have saved my code this time....I edited it but it didnt save my changes....With those Promises it works perfectly but as soon as I add my query to this...It wont work again....I commented my ky query additionally into this queryService.ts so you see if I use it the wrong way ( I personally didnt find anything different on how to use it.)...Is there a way it returns a Promis instantly in my case?
killingsausage
CodeSandbox
dreamy-buck-gysp6s - CodeSandbox
dreamy-buck-gysp6s by killingsausage using ky, loader-utils, react, react-dom, react-query, react-scripts
national-gold
national-gold3y ago
Use async mutationfn eg: mutationFn: async (uuid) => deleteEmbed(xx) Call it with mutateAsync() instead of mutate(). Inside the query function await the ky call. Eg. Res = await ky.delete(). Return res.formData - some guy Onsuccess is running because your query returns before your server finishes work because you aren't waiting for it properly..... probably idk
correct-apricot
correct-apricotOP3y ago
YES I just found the error my deleteEmbed looked like this:
export async function deleteEmbed(serverId: string, uuid: string) {
return api.delete(`${ORIGIN}/embed-manager/`, {
headers: {
'X-Server': serverId,
'X-UUID': uuid
}
}).formData
}
export async function deleteEmbed(serverId: string, uuid: string) {
return api.delete(`${ORIGIN}/embed-manager/`, {
headers: {
'X-Server': serverId,
'X-UUID': uuid
}
}).formData
}
After I removed formData it worked with the refetch after delete prop. because formdata returns a promise now it works yay

Did you find this page helpful?