BLOG
Setting Up React Query in Your Next.js 13 App
illustration of a developer coding with Next.js framework

Mauro Davoli

Frontend Engineer

Jun 4, 2023

3 min read

Next.js

React

Looking to enhance your Next.js 13 app with the power of React Query? This article will walk you through the process of seamlessly integrating React Query into your project and ensuring that the QueryClient is readily available to all components within your component tree.

Let’s dive into it.

Step 1:

By default, Next.js 13 renders all components on the server. However, React Query does not work with server-side rendering out of the box. To overcome this limitation, we need to create a custom provider that renders the QueryClientProvider within a Client Component.

src/app/providers.tsx

"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { useState } from "react";

export default function Providers({ children }: { children: React.ReactNode }) {
  const [client] = useState(new QueryClient());

  return (
    <QueryClientProvider client={client}>
      {children}
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  );
}

Now, let’s incorporate the Provider component into the layout.tsx file.

src/app/layout.tsx

import Providers from "./providers";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Step 2:

To guarantee that data remains isolated between users and requests, while still maintaining a single QueryClient instance per request, we can create a request-scoped singleton instance of QueryClient.

Doing so makes prefetched queries accessible to all components throughout the component tree. This approach also enables us to fetch data within multiple Server Components and utilize <Hydrate> in numerous locations.

src/lib/get-query-client.ts

import { QueryClient } from "@tanstack/query-core";
import { cache } from "react";

const getQueryClient = cache(() => new QueryClient());
export default getQueryClient;

And now let’s create a custom hydrate component

src/components/hydrate-client.ts

"use client";

import { Hydrate as RQHydrate, HydrateProps } from "@tanstack/react-query";

function Hydrate(props: HydrateProps) {
  return <RQHydrate {...props} />;
}

export default Hydrate;

Step 3:

Now that we have React Query set up in our Next.js 13 project, let’s dive into its incredible capabilities. We’ll explore how React Query enables server-side data fetching, state hydration, cache dehydration, and seamless rehydration on the client-side.

With React Query, you can unlock a new level of data management efficiency and responsiveness. Let’s explore these functionalities with a real example.

src/app/profile/page.ts

import { ReactQueryHydrate } from "@/components/react-query-hydrate";
import { client } from "@/lib/api";
import getQueryClient from "@/lib/get-query-client";
import { dehydrate } from "@tanstack/react-query";
import SomeComponent from "@/components/some-component";

async function getUser() {
  const res = await fetch("/user");
  const users = (await res.json());
  return users;
}

export default async function Profile() {
  const queryClient = getQueryClient();
  await queryClient.prefetchQuery(["user"], GetUser);
  const dehydratedState = dehydrate(queryClient);

  return (
	<ReactQueryHydrate state={dehydratedState}>
	  <div>
	    <SomeComponent />
	  </div>
	</ReactQueryHydrate>
  );
}
src/app/components/some-component.tsx

"use client";

import { useQuery } from "@tanstack/react-query";

async function getUser() {
  const res = await fetch("/user");
  const users = (await res.json());
  return users;
}

export default function SomeComponent() {

  const { data, isLoading, isFetching, error } = useQuery({
    queryKey: ["user"],
    queryFn: GetUser,
  });

  return (
    <h1 className="font-bold">{data?.full_name}</h1>
  );
}

Our devtools:

A console with dev tools

Conclusion:

With React Query, you can focus on building intuitive user interfaces and delivering dynamic content without worrying about the complexities of data fetching and state management. It’s a valuable tool that streamlines your development process and helps you create exceptional web applications.

So, embrace the power of React Query and unlock the full potential of your Next.js 13 project. Happy coding!

Mauro Davoli

Frontend Engineer

Jun 4, 2023

3 min read

Next.js

React