Server Component

Like traditional server-side code written in PHP or ASP.NET, React Server Component runs on the server. It enables React apps to fetch data directly within the server components themselves. This makes data management simple, efficient and secure. Have trouble with a slow database connection? Wrap the server component inside a React.Suspense function. It will show a client loading fallback while waiting for the data-fetching logic to complete. Once done, the results can be streamed to the client.

As good as it sounds, it comes with a few constraints. To use this feature effectively, one must keep a clear mental mode of whether a component is intended to run on the server or the client side.

You use the use client directive to mark the boundaries between Client and Server Components. It must sit on top of the component code file above all imports. After that, everything is treated as client components. This design limitation could seriously impact the JS bundle size sent to the client if you have to mark your application root component with ‘use clients. To reduce the size of the JS bundle, it is recommended to move Client Components to the leaves of your component tree when possible and as deep down as possible.

Use Server Components inside a Client Component

When interweaving Client and Server components, it helps to visualise the UI as a component tree on paper. This visualisation can force you to think in React and wisely separate Client Components from Server Components.

Based on React’s rending order (Client Components are rendered after the Client Components), importing a Server Component into a Client Component will result in an additional serve roundtrip and, therefore, is not supported. Instead, you can use React props to mark holes for Server Components in Client Components. When a Client Component is rendered on the client side, the marked holes will be filled with the Server Components that have already been rendered on the server and passed down in React Server Component Payload (RSC Payload)format.

For example:

export default function MyClientComponent({ 
  children 
}: { 
  children: React.ReactNode
}) { 
  /* ... */ 
}

The props passed from the Server to the Client Component must be serialisable.

You can use both Client Components and Server Components inside a Serve Component.

Sharing Data Between Server Components

Unlike Client Components, which can use React Context to share or pass data down as props, Server Components should use the React fetch or cache functions to acquire the same necessary data for different components.

React extends the standard fetch API and can automatically de-dupe requests and memorise data through request memoisation. You don’t need to worry about making duplicate requests in different components or lifting the data request logic to the root of the components tree and passing data down as props. Data returned from the React fetch is automatically stored in the Next.js Data Cache.

Deduplicated Fetch Requests

async function getItem() { 
  // The `fetch` function is automatically memoised 
  // and the result is cached 
  const res = await fetch('https://.../item/1');
  return res.json();
}
 
  // This function is called twice, 
  // but only executed the first time
  const item = await getItem();  // cache MISS 
  
  // The second call could be anywhere in your route
  const item = await getItem(); // cache HIT

Avoiding Unintentional Server & Client Components Poisoning

Code intended for server-side only, e.g., the code that uses an API key to fetch data from an external service, is not for client-side components. Likewise, code that uses the window object is not a good candidate to run on the server. These mistakes are hard to avoid since JavaScript is often portable between the server and the client. One way to overcome the confusion is to use the client-only and server-only packages.

npm install server-only
import 'server-only';
 
export async function getData() { 
  const res = await fetch('https://external-service.com/data', { 
    headers: { 
      authorisation: process.env.API_KEY, 
    }, 
  }) 
  
  return res.json()
}

Any Client Component attempting to import getData() will now receive a build-time error.

Working with third-party libraries

The server Component is still relatively new (as of 05/05/2023). Many third-party packages that use useState, useEffect and other Client Component-only interactivities still need to include the use client directive. You’ll receive an error if you attempt to use these packages inside a Server Component. To use them inside Server Components, you can wrap them with a custom Client Component.

'use client' 
 
import { Popup } from 'super-modal' 
 
export default Popup