10

I'm trying to refetch some queries after one success but it's not working!

I used two ways to handle it by using refetchQueries() / invalidateQueries()

1- onSuccess callback

export const useMutateAcceptedOrder = () => {
  const queryClient = useQueryClient();
  return useMutation(
    ['AcceptedOrder'],
    (bodyQuery: AcceptedOrderProps) => acceptOrder(bodyQuery),
    {
      onSuccess: () => {
        console.log('success, refetch now!');
        queryClient.invalidateQueries(['getNewOrders']); // not work
        queryClient.refetchQueries(['getNewOrders']); // not work
      },
      onError: () => {
        console.error('err');
        queryClient.invalidateQueries(['getNewOrders']); // not work
      },
    },
  );
};

second way

 const {mutateAsync: onAcceptOrder, isLoading} = useMutateAcceptedOrder();
 const acceptOrder = async (orderId: string) => {
    const body = {
      device: 'iPhone',
      version: '1.0.0',
      location_lat: '10.10',
      location_lng: '10.10',
      orderId: orderId,
      os: Platform.OS,
      source: 'mobile',
      token: userInfo.token,
    };
    await onAcceptOrder(body);
    queryClient.refetchQueries(['getNewOrders']); // not work
    queryClient.invalidateQueries(['getActiveOrders']); // not work
    handleClosetModalPress();
  };

sample of query I wanted to refetch after the success

export const useNewOrders = (bodyQuery: {token: string | null}) => {
  console.log('token>>', bodyQuery.token);
  return useQuery(['getNewOrders'], () => getNewOrders(bodyQuery), 
  {
    enabled: bodyQuery.token != null,
  });
};

App.tsx

const App: React.FC<AppProps> = ({}) => {
  const queryClient = new QueryClient();
  if (__DEV__) {
    import('react-query-native-devtools').then(({addPlugin}) => {
      console.log('addPlugin');
      addPlugin({queryClient});
    });
  }

 
  useEffect(() => {
    RNBootSplash.hide({fade: true}); // fade
  }, []);


  return (
    <GestureHandlerRootView style={{flex: 1}}>
      <QueryClientProvider client={queryClient}>
        <BottomSheetModalProvider>
          <AppContainer />
        </BottomSheetModalProvider>
      </QueryClientProvider>
    </GestureHandlerRootView>
  );
};

export default App;

--

EDIT

So after using the react-query-native-devtools Debug tool, I can't see any query in the first tab recorded in the debugger! Although the data fetched well.

So I guess that's why the refetch did not work in this case!

Any query in the first tab I can't refetch it again

Steps to reproduce:

  • open App - Active Tab (first tab)
  • check the status of the queries
  • nothing recorded in the debugger
  • Navigate to any other screen/tab
  • Check the status of queries

all screen queries recorded in the debugger

7
  • Read the docs please. tanstack.com/query/v4/docs/guides/invalidations-from-mutations You need to provide a queryKey property for invalidateQueries. Commented Dec 12, 2022 at 10:40
  • @Binit it's already exist ['getActiveOrders'] Commented Dec 12, 2022 at 10:43
  • The docs use it like these though queryClient.invalidateQueries({ queryKey: ['todos'] }). whereas you're just passing them queryClient.refetchQueries(['getNewOrders']); Commented Dec 12, 2022 at 10:45
  • @Binit same thing not works Commented Dec 12, 2022 at 10:53
  • 1
    @Myzel394 yes i tried this way, but the same issue still :( Commented Dec 27, 2022 at 11:47

4 Answers 4

11

Per https://tkdodo.eu/blog/react-query-fa-qs#2-the-queryclient-is-not-stable:

If you move the client creation into the App component, and your component re-renders for some other reason (e.g. a route change), your cache will be thrown away

In most of the cases you are wrapping your whole app with the query client provider and creating a new instance of the QueryClient object. When your app re-render then a new instance of the query client object will be created with new cache. You can solve that issue by preserving the object inside a state like below:

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

instead of just doing this :

const queryClient = new QueryClient() .

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

Comments

3

I was facing the same issue and haven't been able to find a proper solution for this, however I have found a hacky workaround. You just call your refetch function or invalidate queries inside a setTimeout.

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
0

This is a relatively old question, but I ran into the same problem. I ended up solving my problem in a few ways:

#1 I changed my update API endpoints so that after modifying a record, it sends the whole new record back, and I end up doing queryClient.setQueryData to update the local cache.

#2 Even though queryClient.invalidateQueries is plural, I switched everything to singular invalidations per query key.

#3 Grepped my code base to ensure there is only 1 instance of new QueryClient and everywhere else is using useQueryClient

#4 Last and perhaps least, I added .then() to invalidateQueries just in case the async code was somehow never being executed.

Note https://tanstack.com/query/v4/docs/react/guides/query-invalidation#query-matching-with-invalidatequeries The invalidate query call only seems to work if I added the mentioned fetchType param.

Here is the documentation for https://tanstack.com/query/v4/docs/react/reference/QueryClient#queryclientsetqueriesdata

Below is a full example of what I did above.

const _updateCharacter = useMutation<Character, Error, Character>({
        mutationFn: (character: Character) => api.update_character(character),
        onSuccess: (updated_character) => {
            queryClient.setQueryData(
                ['book', activeBook.id, 'character', updated_character.id],
                () => updated_character
            )

            queryClient
                .invalidateQueries({
                    queryKey: ['book', activeBook.id, 'characters'],
                    exact: true,
                    refetchType: 'active'
                })
                .then()
        },
        onError: (error) => {
            console.log(error)
        }
    })

This is for a detailed book inventory management system. The goal is to update the details for a specific character BUT, in addition, update a list of all characters to reflect a name change, note word count, and the last updated field.

Not relevant, but every Character record has an internal id primary key and an exposed snowflake unique identifier, so that's why I can get away with just passing the record to the API without its associated book.

I hope this helps someone else and saves them from slowly losing their mind as nothing seems to work.

Comments

0

As the example in documentation (https://tanstack.com/query/latest/docs/framework/react/reference/QueryClientProvider#queryclientprovider), you have to instantiate your queryClient outside of your app component.

This solved the problem for me.

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient()

function App() {
  return <QueryClientProvider client={queryClient}>...</QueryClientProvider>
}

Comments

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.