hand sketched logo of electrons orbiting a nucleus

🐥 Hybrid Server-Client Data Fetching Pattern

One possible pattern for fetching data in a hybrid server-client NextJS app

Overview

With NextJS 13 and React 18, we have a new ability to get data server-side via react server components.

Given that, how should we make sure that data is hydrated into our client component fetching patterns?

Hydration with SWR Config

We can use SWRConfig (which is using the provider pattern) via the value prop to pass in fallback object with our server gotten data. Then any useSWR nested in that component tree will have access to that fallback data when it tries to fetch data.

To actually make this work we need to make a wrapper SWRProvider component that will wrap SWRConfig as it is not useable as is in server components

// SWRProvider.tsx
'use client';

import { SWRConfig } from 'swr';

export const SWRProvider = ({ fallback, children }) => {
  return <SWRConfig value={{ fallback }}>{children}</SWRConfig>;
};

Then we can use it in our server component like so:

// MyServerPage.tsx

import { SWRProvider } from './SWRProvider';

export default function MyServerPage() {
  const { data: user, error } = await fetchUser();

  return (
    <SWRProvider fallback={{ user }}>{/* your react tree here */}</SWRProvider>
  );
}

Then in any client component that is nested in that tree, when we use useSWR to fetch a user, the fallback data will be used instantly until the client-side fetch is complete.

// MyClientComponent.tsx

import useSWR from 'swr';

export default function MyClientComponent() {
  const { data: user, error } = useSWR('user', fetchUser);

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.bio}</p>
    </div>
  );
}