Optimizing Server-Side Data Fetching with Next.js and React Query

0

### Optimizing Server-Side Data Fetching with Next.js and React Query

Server-Side Rendering (SSR) and Client-Side Rendering (CSR) can be consistently performed using the combination of Next.js and React Query. In this article, we will explore step-by-step how to efficiently fetch and manage data using `getServerSideProps`, `dehydrate()`, `QueryClient`, and `HydrationBoundary`.

1. getServerSideProps for Server-Side Data Fetching

The `getServerSideProps` function in Next.js supports server-side rendering and runs on every page request. It allows fetching the latest data and passing it to the page.

import { GetServerSideProps } from 'next';

export const getServerSideProps: GetServerSideProps = async (context) => {
  const { params, req, query } = context;

  // Example: Fetching dynamic route value from params
  const id = params?.id;

  // Example: Accessing request headers from req
  const userAgent = req.headers['user-agent'];

  // Example: Fetching query string value from query
  const searchQuery = query.search;

  // Fetching data and passing it to the page component
  const data = await fetchData(id, searchQuery);

  return {
    props: {
      data,
      userAgent,
    },
  };
};

const MyPage = ({ data, userAgent }) => {
  return (
    <div>
      <h1>Data: {data}</h1>
      <p>User Agent: {userAgent}</p>
    </div>
  );
};

export default MyPage;

2. Understanding QueryClient in React Query

React Query is a library that simplifies data fetching and caching. `QueryClient` is the core instance of React Query responsible for managing data state, caching, synchronization, etc.

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

const queryClient = new QueryClient();

function MyApp({ Component, pageProps }) {
  return (
    <QueryClientProvider client={queryClient}>
      <Component {...pageProps} />
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  );
}

export default MyApp;

3. Using dehydrate() for Server-Side Data Serialization

To fetch data on the server side and serialize it to send to the client, use the `dehydrate()` function. This allows transferring React Query’s cached data to the client.

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

export async function getServerSideProps() {
  const queryClient = new QueryClient();

  await queryClient.prefetchQuery('todos', fetchTodos);

  return {
    props: {
      dehydratedState: dehydrate(queryClient),
    },
  };
}

function TodosPage({ dehydratedState }) {
  return (
    <HydrationBoundary state={dehydratedState}>
      <Todos />
    </HydrationBoundary>
  );
}

export default TodosPage;

4. Restoring Client-Side Data: HydrationBoundary

To restore serialized data on the client side, use the `HydrationBoundary` component. This ensures data consistency between the server and client.

import { HydrationBoundary } from 'react-query';

function TodosPage({ dehydratedState }) {
  return (
    <HydrationBoundary state={dehydratedState}>
      <Todos />
    </HydrationBoundary>
  );
}

export default TodosPage;

Summary and Conclusion

In this article, we explored how to use Next.js and React Query to consistently fetch and manage data on both server-side and client-side. By leveraging `getServerSideProps`, `QueryClient`, `dehydrate()`, and `HydrationBoundary`, we can pre-fetch data on the server and restore it on the client, providing a fast and consistent user experience. This process helps maintain data consistency and optimize initial loading times.

Implement these methods to make your Next.js application more efficient and high-performing with server-side data fetching.

Leave a Reply