5

I am using react-query (actually tanstack/react-query v4) to query from and mutate a db. Based on docs and research, I gather that useQuery will automatically refetch from the server if/when the server-state differs from the cached state.

However, after I useMutation to update my db, the impacted query does not immediately refetch.

I know that the useMutation is working based on viewing the db on server-side, but also because I can manually refetch using react-query dev tools, and get the new values just fine.

On reading, I have tried two approaches:

  const addMover = useMutation({
    mutationFn: (newMover) => { ... },
    onSuccess: () => {
      queryClient.invalidateQueries(["movers"]);
      console.log("The mutation is sucessful!");
    },
  });

---> When this mutation gets run, I do see the 'onSuccess' console.log() coming through, but the query still shows as 'stale' in the dev-tools and does not get re-rendered.

  • I also tried (in a different place) the "SetQueryData" pattern from the useMutation response, as outlined in the docs...
const handleDelete = useMutation(
    {
      mutationFn: (wktID) => { ... },
      onSuccess: (data) => {
        queryClient.setQueryData(["workouts", [activeMover]], data);
      },
    }
  );

My expectation from either approach is simply that the mutated db gets re-queried and re-rendered. I'd prefer to SetQueryData and save a network request, but either approach would make me happy :).

6
  • Where is the ["movers"] query used? Commented Feb 10, 2023 at 19:20
  • ["movers"] is used to populate a sidebar nav, and then activeMover (selected) is saved in app-wide state and re-useQuery'd on many different components. I am assuming here that react-query is accessing from state when/where possible, rather than refetching at each instance, in each component. Does that answer your question @SlavaKnyazev ? Commented Feb 11, 2023 at 20:44
  • Could you please provide more code about the useQuery(["movers"]) and useQuery(["workouts", [activeMover]])? Cause I'm thinking that maybe you triggered not the same query keys. Commented Feb 13, 2023 at 10:20
  • @haptn Thanks for the question--using the tanstack-query dev tools, I can see what queries are held in cache, and their query keys are listed, and in both cases showed above I have matched those query keys exactly. Is that what you mean? If not, I can share the initial useQuery call.... ? Commented Feb 15, 2023 at 14:52
  • @tkdodo any chance you could chime in here?? Commented Feb 15, 2023 at 14:52

3 Answers 3

8

I was able to solve this! The issue here was that I was not explicitly returning anything from the mutationFnc in my useMutation definition.

This meant that onSuccess was getting triggered by the return of an 'OPTIONS' request, and not the actual 'POST', and since at that point the DB had not been updated, there was nothing new to fetch w/ useQuery.

By adding a 'return' to the function, it now waits for the Promise before triggering onSuccess, and my mutation now gets rendered by the useQuery. Like this...

const addMover = useMutation({
    mutationFn: (newMover) => { ... },
    onSuccess: () => {
      return queryClient.invalidateQueries(["movers"]);
      console.log("The mutation is sucessful!");
    },
  });

So be sure to treat your mutationFnc as a proper async function, that waits for the Promise to get resolved! (Duh :).

Sign up to request clarification or add additional context in comments.

6 Comments

Welcome to Stack Overflow! Make sure to always include code on your answer! How do I write a good answer?
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
console.log will not run because you already returned from onSuccess
OMG is that in documentation? I just lost like an hour trying to figure it out
The docs don't say anything explicit, but I'm guessing my use of curly braces requires an explicit return. Glad it helped!
|
-1

I was encountered into same issue and I found it's proper solution by digging into react-query documentation.

How I was using it.

const { data: transactions, refetch }: { data: any; refetch: Function } =
useQuery('ledger', getTransactions, {
  enabled: !!fundId,
  refetchInterval: 30000,
});

const { mutate: postSignal } = useMutation('ledger', sendSignal, {
onSuccess: (response: any) => {
  return new QueryClient().invalidateQueries('ledger');
  },  
});

So after using above code I was having same issue, actually what is happening here refetch is meant to refetch manually and it conflicts with

refetchInterval

If you want to refetch manually you have to remove refetchInterval.

Documentation Link

Comments

-3

If you want to re-fetch data after mutation you edit your mutation and leave it like this:

const [createHabit, { error, loading }] = useMutation(CREATE_HABIT_MUTATION, {
    refetchQueries: [{ query: HABITS_QUERY }],
  });

Here you can find an example.

2 Comments

If you're going to provide a link for reference it's a better idea to link to the official docs rather than a random blog. Also, the example in the article is not based on react-query which is the library OP is using.
Thanks @jcobo1 for the reply, but I'm not using Apollo or GraphQL for this project, just SQLite and flask.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.