React server components
Render React components on the server
Intro
React Server components are introduced with React version 18 and are adopted in Next.js 13 App folder. With React server components we can now render components both on the server and on the client.
Motivation
Zero-Bundle-Size components
Developers constantly have to make choices about using third-party packages. Using a package to render some markdown or format a date is convenient for us as developers, but it increases code size and hurts performance for our users.
app/rsc/page.tsx
JavaScript
// NOTE: *before* Server Components

import marked from 'marked'; // 35.9K (11.2K gzipped)
import sanitizeHtml from 'sanitize-html'; // 206K (63.3K gzipped)

function NoteWithMarkdown({text}) {
  const html = sanitizeHtml(marked(text));
  return (/* render */);
}
NOTE: With Next.13 App directory all components are by default server components so if we want our component to be rendered on the client we have to use use clientdirective on top on the file before any import
Server Components allow developers to render static content on the server or during the build, taking full advantage of React’s component-oriented model and freely using third-party packages while incurring zero impact on bundle size.
app/rsc/page.tsx
JavaScript
// Server Component === zero bundle size

import marked from 'marked'; // zero bundle size
import sanitizeHtml from 'sanitize-html'; // zero bundle size

function NoteWithMarkdown({text}) {
  // same as before
}
Full Access to the Backend
app/rsc/page.tsx
JavaScript
import db from 'db';

async function Note({id}) {
  const note = await db.notes.get(id);
  return <NoteWithMarkdown note={note} />;
}
Usage
Writing code

- Server components cannot use browser-only APIs


- Server components cannot use React hooks


- Server components cannot use Context

React Server Components are useful for rendering the skeleton of a page, while leaving the interactive bits to the so-called client components.
client-server.png
Server components can import client components.
Passing Server components to Client components as Props
Instead, when designing Client Components you can use React props to mark holes for Server Components. The Server Component will be rendered on the server, and when the Client Component is rendered on the client, the hole will be filled in with the rendered result of the Server Component.
A common pattern is to use the React children prop to create the hole.
app/rsc/page.tsx
TypeScript
'use client';
 
import { useState } from 'react';
 
export default function ExampleClientComponent({
  children,
}: {
  children: React.ReactNode;
}) {
  const [count, setCount] = useState(0);
 
  return (
    <>
      <button onClick={() => setCount(count + 1)}>{count}</button>
 
      {children}
    </>
  );
}
app/rsc/page.tsx
JavaScript
// This pattern works:
// You can pass a Server Component as a child or prop of a
// Client Component.
import ExampleClientComponent from './example-client-component';
import ExampleServerComponent from './example-server-component';
 
// Pages in Next.js are Server Components by default
export default function Page() {
  return (
    <ExampleClientComponent>
      <ExampleServerComponent />
    </ExampleClientComponent>
  );
}
Folders and Files
App Router
Folders are used to define routes. A route is a single path of nested folders, following the hierarchy from the root folder down to a final leaf folder that includes a page.js file.
approuter.png
Layouts
Layouts are one of the biggest new functionality made possible by the new App Router.
Next.js needs one root layout component
Layouts are defined using the convention layout.tsx in the app directory: Next.js will automatically wrap all pages within the folder where the layout is defined.
app/rsc/page.tsx
TypeScript
export const metadata = {
  title: 'Next.js Tutorial',
  description: 'A Next.js tutorial using the App Router',
};
 
async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang={'en'}>
      <body>{children}</body>
    </html>
  );
}
 
export default RootLayout;