Why use useQueryClient from react-query library?
Asked Answered
K

3

15

In the quick start docs of react-query here there is the following example:

// Create a client
const queryClient = new QueryClient();

const App = function () {
  return (
    // Provide the client to your App
    <QueryClientProvider client={ queryClient }>
      <Todos />
    </QueryClientProvider>
  );
};

const Todos = function () {

  // Access the client
  const queryClient = useQueryClient();

  // ...

  return (
    <>
      ...
    </>
  );
};

but I cannot understand why I should use the useQueryClient hook inside the Todos.

// Access the client
const queryClient = useQueryClient();

I mean couldn't I just export the the queryClient instance from my main file:

// App.js
export const queryClient = new QueryClient();

and then import it immediately inside Todos ?

// Todos.js
import { queryClient } from './App';

The reason I am asking this is because I want to use the queryClient instance apart from react (maybe inside a listener function from another library) and I was wondering that if I can only access it from a react hook (in order to not mess something up) then I won't be able to use it in some other way.

Kerry answered 19/3, 2022 at 18:34 Comment(0)
G
9

There are basically three reasons why useQueryClient is preferred:

  1. It decouples your App from the actual implementation (the biggest win for me). This is especially relevant when doing testing. For example, when testing erroneous endpoints, react-query will do 3 retries with exponential backoff. That means your tests take longer and might even time-out for those cases. This can be solved by turning off retries for tests globally, via the QueryClient. You can just provide a different QueryClient to wrap your component in your test that has retries turned off.
  2. It is sometimes necessary to create the QueryClient inside the App component (stable, on react state or an instance ref). For example, if you need to closure over values provided from another hook in your defaults passed to the QueryClient, or, when doing server-side-rendering, where this is advised to avoid leaking data between requests and users.
  3. react-query internally uses useQueryClient to get the nearest QueryClient from the Provider. So you need to create the Provider anyways.
Gingergingerbread answered 7/4, 2022 at 18:34 Comment(4)
Can you explain more on how the useQueryClient still the preferred way when QueryClient is needed outside of react component tree? (eg. need to call queryClient.fetchQuery directly in some api.js files)Gezira
tkdodo.eu/blog/react-query-fa-qs#why-should-i-usequeryclientGingergingerbread
I agree with this answer however I would like to comment on the first point: If you're using something like react-hooks-testing-library then you can create a custom render function that would use wrapper with QueryClientProvider where you can provide custom queryClient. Since this is something you'd probably want for all tests the tradeoff is really not that big, I guess?Funny
no, this is exactly my point. If you just import the queryClient directly in your custom hook, you can't wrap it in a test. React Query will see the wrapped one from the test, but your custom hook will import the production one. That's exactly why using useQueryClient is better than importing it directly ....Gingergingerbread
F
1

yes, I think I got your doubt.

You can do this, is perfectly fine;

// App.js
export const queryClient = new QueryClient();

This is mostly how providers and context works, is just a bag to store global variables, and you will have access to the actual instance of that variable inside your ReactComponentTree. That's why your <App/> must be wrapped with the provider to provide that context and use it from inside with useVariable()**

The thing is react-query provides functionalities that are tied to the react lyfecycle, and the preferable magic happens thanks to the useQuery() module and you won't be able to use that externally.

But, if you extract just the QueryClient to be called outside from React that could works. You just have to be aware of the implementation for the functionality that you will be using, mostly should works because tanner has known of separation of concerns, so probably the QueryClient provide specifics functions decoupled from React or any hook. Still be careful. And you can check the implementation on his repo, and ask more in deep to tanner directly, is a workaholic active on twitter xD, https://github.com/tannerlinsley.

Furey answered 24/3, 2022 at 16:36 Comment(0)
W
0

QueryClientProvider is a React context provider. In React, you access the context via hooks because there is no guaranteed universal context. The hook returns you the most immediate context from the caller component's ancestors.

You cannot export it from App.js because it does not have a QueryClientProvider above it. You could work around it. But that would not work either. You can only call the hook within a component and you cannot export something from inside the component. There is also the possibility of the whole site re-rendering with every request depending on your implementation.

Overall, it seems like a bad idea.

Weanling answered 24/3, 2022 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.