I have created a function which adds a specific item to my diary. 9/10 times everything works, which means that there is nothing wrong with the code?
However rarely I add the item to my diary, but I don’t see the update values, even thought I activated queryClient.invalidateQueries()
method, the value is updated on my server, because when I manually refresh I see the updated diary again.
Does this mean that by the time I activate invalidatequeries method, the update has not reached my server and that is why I am seeing stale data? But what would I do in that case?
Here is the function:
const newAddItemFunction = () => { const day = newDiary?.[currentDay]; if (day && selectedMealNumber && selectedItem) { setSavingItem(true); NewAddItemToDiary({ day, selectedMealNumber, selectedItem, }); queryClient.invalidateQueries(["currentDiary"]).then(() => { toast.success(`${selectedItem.product_name} has been added`); }); router.push("/diary"); } };
Here is my custom hook(useFirestoreQuery is just custom wrapped useQuery hook for firebase):
export const useGetCollectionDiary = () => { const user = useAuthUser(["user"], auth); const ref = collection( firestore, "currentDiary", user.data?.uid ?? "_STUB_", "days" ); return useFirestoreQuery( ["currentDiary"], ref, { subscribe: false, }, { select: (data) => { let fullDaysArray = [] as Day[]; data.docs.map((docSnapshot) => { const { id } = docSnapshot; let data = docSnapshot.data() as Day; data.documentId = id; fullDaysArray.push(data); }); fullDaysArray.sort((a, b) => a.order - b.order); return fullDaysArray; }, enabled: !!user.data?.uid, } ); };
NewAddItemToDiary function is just firebase call to set document:
//...json calculations setDoc( doc( firestore, "currentDiary", auth.currentUser.uid, "days", day.documentId ), newDiaryWithAddedItem );
Advertisement
Answer
9/10 times everything works, which means that there is nothing wrong with the code?
It indicates to me that there is something wrong with the code that only manifests in edge cases like race conditions.
You haven’t shared the code of what NewAddItemToDiary
is doing, but I assume it’s asynchronous code that fires off a mutation. If that is the case, it looks like you fire off the mutation, and then invalidate the query without waiting for the query to finish:
NewAddItemToDiary({ day, selectedMealNumber, selectedItem, }); queryClient.invalidateQueries(["currentDiary"]).then(() => { toast.success(`${selectedItem.product_name} has been added`); });
Mutations in react-query have callbacks like onSuccess
or onSettled
where you should be doing the invalidation, or, if you use mutateAsync
, you can await
the mutation and then invalidate. This is how all the examples in the docs are doing it:
// When this mutation succeeds, invalidate any queries with the `todos` or `reminders` query key const mutation = useMutation(addTodo, { onSuccess: () => { queryClient.invalidateQueries('todos') queryClient.invalidateQueries('reminders') }, })