Home  >  Q&A  >  body text

Revalidate after mutation in reaction query: step-by-step guide

I implemented the basic implementation of data retrieval and update using react-query on my next.js application. My goal is to update the data after mutation. Currently, the data is only updated when the tab is refreshed. But it won't change without user interaction.

I found that the data update happening on tab refresh is due to refetchOnWindowFocus default behavior.

But how does it become invalid after the data is updated on the server side? Here is the relevant code snippet.

Note: I am using Hydration to use the react-query SSR functionality. document

_app.jsx

const [queryClient] = React.useState(() => new QueryClient());

  return (
    <QueryClientProvider client={queryClient}>
      <Hydrate state={pageProps.dehydratedState}>
          <Component {...pageProps} />
      </Hydrate>
    </QueryClientProvider>

Home.jsx

const {data} = useQuery({
    queryKey: [queryKeys.key],
    queryFn: fetchData,
    staleTime: 1000 * 10, // this doesn't affect on anything
    //refetchInterval: 2000, this updates every 2 seconds
  });

  return (
    <div>
      <Article articles={data} />
    </div>
  );
   export const getServerSideProps = async () => {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery([queryKeys.key], fetchData);
  return { props: { dehydratedState: dehydrate(queryClient) } };
};

Article.jsx

const Article = ({articles}) => {
  const [title, setTitle] = useState("");
  const queryClient = new QueryClient();

  const { mutate } = useMutation({
    mutationFn: async (article) => {
      return await axios.post(url, article);
    },
    onSuccess: (data) => {
      console.log("data", data) // data is displayed, onSuccess is called
      queryClient.invalidateQueries({ queryKey: [queryKeys.key] });
    },
  });

  const changeTitleHandleClick = () => {
    mutate({
      id: new Date(),
      title: title
    });
    setTitle("");
  };
  ....

Any help would be greatly appreciated

Update: refetchInterval:2000Updates every 2 seconds, but this triggers a network request every 2 seconds, so I'm not sure this is a best practice for revalidation.

UPDATE: onSuccess The console inside the method is showing on mutation, which means there is something wrong with the logic since this should work even if the keys are different: queryClient .invalidateQueries() where I did not specify any key but triggered all queries. But even then it won't be updated. Why?

P粉752290033P粉752290033230 days ago407

reply all(2)I'll reply

  • P粉677684876

    P粉6776848762024-03-26 11:50:35

    The way you implement mutation, it should re-fetch the query after successful mutation:

    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: [queryKeys.key] });
    },

    If this doesn't work, your mutation was unsuccessful. Check if the onSuccess callback is called.

    If the onSuccess callback is called, but your query is not re-fetched, it may mean that the queryKey does not match. For testing purposes, try expanding the filter to:

    queryClient.invalidateQueries()

    Should re-fetch all queries. If it works, you know your queryKey filter doesn't match.

    Look carefully, you are failing:

    queryKey: [queryKeys.key]

    But in your custom hook you are using:

    queryKey: [queryKeys.articles]

    So it looks like they are indeed different and therefore not matching. Also, be sure to use @tanstack/react-query-devtools to better understand the queries and keys in the cache.

    reply
    0
  • P粉231079976

    P粉2310799762024-03-26 11:47:03

    The problem is that in the component Article.jsx I create a new QueryClient on every render, so it gets a new cache and therefore is not updated.
    Instead, I have to use the useQueryClient hook, which returns the current instance.
    const queryClient = useQueryClient();

    reply
    0
  • Cancelreply