Skip to content
Advertisement

Why do I see stale data even after invalidating my queries?

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
    );

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')
   },
 })
Advertisement