Dwarves
Memo
Type ESC to close search bar

React Server Components, NextJs Route and Data Fetching

React Server Components, NextJs Route and Data Fetching

React Server Components (RSCs) offer the flexibility to decide where to render components based on their purpose, diverging from the client-side rendering approach of Single-Page Applications. By breaking down the page into smaller components, it becomes evident that many components are non-interactive and can be rendered on the server as Server Components. This can improve performance, reduce bundle size and also improve the initial page loading time.

What are React Server Components?

Why Server Components?

Server Components make your app load faster and use less JavaScript. The base runtime is fixed and cacheable, and more JavaScript is only added when you need client-side interactivity with Client Components.

Next.js renders the initial HTML on the server and sends it to the browser. The browser then enhances the HTML with interactivity by loading the Next.js and React runtime asynchronously. This lets the client take over the app and handle user interactions.

How to use Server Components in Next.js?

In the latest release of Next.js, they have introduced Server Components as essential requirements to be utilized in the construction of their single-page applications (SPAs).

To enhance code maintainability and readability, it is recommended to use the file naming convention of .server.(jsx|tsx) for Server components, and .client.(jsx|tsx) for Client components.

In Client components use the use client directive at the top of any file that contains client-side components or logic. This will mark the boundary between server-only and client.

Here is an example of a simple RSC that fetches some data from a database and renders it on the server:

// app/Greeting.server.js
import db from './db'

export default function Greeting({ name }) {
  // Fetch data from the database on the server
  const message = db.getGreeting(name)

  // Return a plain object with the data
  return { message }
}

And here is how you can use it in your client-side component:

// app/Homepage.client.js
'use client' // Mark this file as client-only
import Greeting from './Greeting.server' // Import the RSC

export default function Homepage() {
  // Use the RSC as a regular component
  return (
    <div>
      <h1>Welcome to Next.js!</h1>
      <Greeting name="Alice" /> // Render the RSC
    </div>
  )
}

use client marks the transition from server-only to client code. It goes at the top of a file, before any imports, to indicate that everything below it belongs to the client bundle. This includes any modules or components that are imported in the file.

Server Components are incompatible with custom hooks that use state, effects, or browser-only APIs.

What are the benefits of using Server Components with Next.js?

Using RSC with Next.js can bring several benefits to your application, such as:

Pattern for using Server Components

'use client';

<ClientComponents>
  <ServerComponents>
</ClientComponents>
<ClientComponents>{children} // The children is Server Components</ClientComponents>
import 'server-only'

export async function getData() {
  // Do get the data
}

Server Components Data Fetching in Next.js

With the new features implemented to the fetch WebAPI and make the use of async/await in Server Components, now the fetch can provide us a higher performance on caching/revalidating fetched data and prevent memory caching duplicate requests.

Next.js caches the data from fetch requests by default. When Next.js renders a page on the server and comes across a fetch, it will look for the data in the cache first. If the data is there, it will use it. If not, it will fetch and store the data for later requests. Or we can use native cache function of react to manually cache the data if unable to use fetch WebAPI.

For revalidating the cache data, that the fetch API introduced two ways are:

We can use the Server Actions in handling actions in Client Components interactive actions by adding use server in the handling action:

export default function Form() {
  async function handleSubmit() {
    'use server'
    // ...
  }

  async function submitPicture() {
    'use server'
    // ...
  }

  return (
    <form action={handleSubmit}>
      <input type="text" name="name" />
      <input type="image" formAction={submitImage} />
      <button type="submit">Submit</button>
    </form>
  )
}

If we don’t use fetch to cache the API on server code, we can still fetch data on the client side. We suggest using libraries like SWR or React Query with Client Components. Later, we’ll also be able to use React’s use() hook to fetch data in Client Components.

If we planning to use react-query on the project, we can use the approach with initialData in useQuery or Hydrate .

Conclusion

In summary, React Server Components (RSCs) provide a powerful way to render React applications by enabling collaboration between server and client components. They improve performance, reduce bundle size, and enhance initial page loading time. By breaking down the page into smaller components, non-interactive parts can be rendered on the server as Server Components, resulting in faster page loads and better user experience. RSCs in Next.js offer benefits such as improved performance, reduced bundle size, and simplified data fetching. Overall, RSCs offer developers a more efficient and seamless rendering experience for React applications.

References