Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-Query and Query Invalidation Question

I don't really know how to ask clearly but, I will paste my code first and ask below.

function useToDos() {
  const queryCache = useQueryCache();
  const fetchTodos = useQuery(
    'fetchTodos',
    () => client.get(paths.todos).then(({ data }: any) => data),
    { enabled: false }
  );

  const createTodo = async ({ name ) =>
    await client.post(paths.todos, { name }).then(({ data }) => data);

  return {
    fetchTodos,
    createTodo: useMutation(createTodo, {
      onMutate: newItem => {
        queryCache.cancelQueries('fetchTodos');
        const previousTodos = queryCache.getQueryData('fetchTodos');
        queryCache.setQueryData('fetchTodos', old => [
          ...old,
          newItem,
        ]);
        return () => queryCache.setQueryData('fetchTodos', previousTodos);
      },
    }),
  };
}

As you can see, I am trying to create my own custom hooks that wrap react-query functionality. Because of this, I need to set my fetchTodos query to be disabled so it doesn't run right away. However, does this break all background data fetching?

Specifically, when I run createTodo and the onMutate method triggers, I would ideally like to have the fetchTodos query update in the background so that my list of todos on the frontend is updated without having to make the request again. But it seems that with the query initially set to be disabled, the background updating doesn't take effect.

As I don't think wrapping react-query hooks into a library of custom hooks is a very great idea, I will probably have more questions about this same setup but for now, I will start here. Thank you. 😊

like image 484
Yuschick Avatar asked Dec 06 '25 10:12

Yuschick


1 Answers

The mutation does not automatically triggers a refetch. The way to achieve this using react-query is via queryCache.invalidateQueries to invalidate the cache after the mutation. From the docs:

The invalidateQueries method can be used to invalidate and refetch single or multiple queries in the cache based on their query keys or any other functionally accessible property/state of the query. By default, all matching queries are immediately marked as stale and active queries are refetched in the background.

So you can configure the useMutation to invalidate the query when the mutation settles. Example:

function useToDos() {
  const queryCache = useQueryCache();
  const fetchTodos = useQuery(
    'fetchTodos',
    () => client.get(paths.todos).then(({ data }: any) => data),
    { enabled: false }
  );

  const createTodo = async ({ name ) =>
    await client.post(paths.todos, { name }).then(({ data }) => data);

  return {
    fetchTodos,
    createTodo: useMutation(createTodo, {
      onMutate: newItem => {
        queryCache.cancelQueries('fetchTodos');
        const previousTodos = queryCache.getQueryData('fetchTodos');
        queryCache.setQueryData('fetchTodos', old => [
          ...old,
          newItem,
        ]);
        return () => queryCache.setQueryData('fetchTodos', previousTodos);
      },

      onSettled: () => {
        cache.invalidateQueries('fetchTodos');
      }

    }),
  };
}
like image 79
Otacilio Lacerda Avatar answered Dec 09 '25 00:12

Otacilio Lacerda