How to use React Query on Nextjs
Tags: react, nextjs, typescript, programming
Published: 2023-02-15 15:05:36

### Introduction

React query is a tool for creating hooks for fetching, caching and updating asynchronous data [repository](https://github.com/TanStack/query).

### Motivation

Fetching data from your backend is one of the most performance killers features of any frontend, and it really helps to keep a copy of the fetched data in the browser, but it's not always possible, or convenient to build a Redux store, so react-query is a good alternative for managing API results without having to do a lot of work for it, and without having to fetch it again every time you need it.
With react-query, you have a shared source for all components that use that data, with a cache and mutations for updating the state across your application.

As their docs say:

> React Query replaces the boilerplate code and related wiring used to manage cache data in your client state and replaces it with just a few lines of code.

You can check their motivation on their [page](https://tanstack.com/query/latest/docs/react/overview?from=reactQueryV3&original=https%3A%2F%2Ftanstack.com%2Fquery%2Fv3%2Fdocs%2Foverview#motivation)

### Usage

- First, you have to configure the provider `QueryClientProvider` like this:

``` typescript
// _app.tsx

import { QueryClient, QueryClientProvider } from 'react-query';

export default function App({Component, pageProps}) {
  const queryClientRef = useRef<QueryClient>();

  if (!queryClientRef.current) {
    queryClientRef.current = new QueryClient();
  }

  return (
    <React.Fragment>
      <Head>
        ...
      </Head>
      <QueryClientProvider client={queryClientRef.current}>
        <Component {...pageProps} />
        <ReactQueryDevtools initialIsOpen={false} />
      </QueryClientProvider>
    </React.Fragment>
  );
}
```

If you don't know what a provider is, visit [the react docs](https://reactjs.org/docs/context.html).

`ReactQueryDevtools` is an integrated tool from react-query that helps tremendously with inspecting and debugging queries.

- Secondly, you have to make a service, for example at `/lib/services/getClientsService.ts`

``` typescript
// /lib/hooks/getClientsService.ts

export async function getClients(): Promise<NetworkResponse<Client>> {
  return axios.get(`/api/clients`).then(response => response.data);
}
```

- And finally, a hook for consuming the service and giving react query the retry options:


``` typescript
// /lib/hooks/useClients.ts

export function useClients() {
  const { data, status } = useQuery<NetworkResponse<Client>, AxiosError>(
    `/clients`,
    () => getClients(),
    {
      retry: true,
      refetchOnWindowFocus: false,
      refetchOnReconnect: false
    }
  );

  return { data: data, status };
}
```

Now you're good to go using the hook in every component necessary, like so:

``` typescript

export default function Clients() {
  const { clients } = useClients()

  return (
    <>
      <div className="flex flex-wrap mt-4">
        <div className="w-full mb-12 px-4 h-full">
          {clients && clients.length > 0 ? (
            <ClientsTable clients={clients} />
          ) : (
            <Spinner />
          )}
        </div>
      </div>
    </>
  );
}
```

And there you have it, it isn't hard at all to build and it has a very good performance.

Have a good day :).