Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. React Dictionary
  3. Server Components

Server Components

Since: React 19(2024)

React Server Components are components that run only on the server. They are not sent to the client as a JavaScript bundle — only the rendered result (HTML or a serialized React tree) is delivered to the browser. Adopted by frameworks such as Next.js App Router, they bring benefits including smaller bundle sizes, direct access to databases and APIs, and protection of sensitive information.

Differences from Client Components

ItemServer ComponentsClient Components
Execution environmentServer only.Browser (also executed on the server during SSR).
JS bundleNot included in the client bundle.Sent to the client.
InteractivityEvent handlers, state, and hooks cannot be used.Event handlers, state, and hooks can be used.
Data accessCan directly access databases, the file system, and server-only APIs.Access only through API endpoints.
DeclarationDefault (nothing written at the top of the file).Write 'use client' at the top of the file.

Basic Usage

// UserProfile.jsx (Server Component)
// Without 'use client' at the top,
// it is automatically treated as a Server Component

// A server-only data fetching function (e.g., DB access)
async function getUser(id) {
  // This runs only on the server, so
  // connection strings and API keys can be used directly
  const res = await fetch('https://api.example.com/users/' + id, {
    // In Next.js, the cache option controls caching behavior
    cache: 'no-store',
  });
  return res.json();
}

// async/await can be used to fetch data directly
// Client Components require hooks (such as useEffect),
// but Server Components just need to be defined as async functions
export default async function UserProfile({ userId }) {
  const user = await getUser(userId);

  return (
    <section>
      <h2>{user.name}</h2>
      <p>Email: {user.email}</p>
      <p>Registered: {user.createdAt}</p>
    </section>
  );
}

Sample Code

An example of a Server Component fetching and displaying data while delegating only the interactive parts to a Client Component.

// app/articles/page.jsx (Server Component)
// This file runs only on the server
// It becomes a Server Component by not writing 'use client'

import LikeButton from './LikeButton'; // Import a Client Component

// Fetch the article list directly on the server
async function getArticles() {
  const res = await fetch('https://api.example.com/articles', {
    // Revalidate the cache every 60 seconds
    next: { revalidate: 60 },
  });

  if (!res.ok) {
    throw new Error('Failed to fetch articles');
  }

  return res.json();
}

export default async function ArticlesPage() {
  // Receive data directly with await
  // No useEffect + useState pattern needed
  const articles = await getArticles();

  return (
    <main>
      <h1>Articles</h1>
      <ul>
        {articles.map(function(article) {
          return (
            <li key={article.id}>
              <h2>{article.title}</h2>
              <p>{article.summary}</p>

              {/* LikeButton requires a click event, so it is
                  separated as a Client Component */}
              <LikeButton articleId={article.id} initialCount={article.likes} />
            </li>
          );
        })}
      </ul>
    </main>
  );
}
// app/articles/LikeButton.jsx (Client Component)
// Interactive operations (click, state) are needed, so
// 'use client' is declared at the top of the file
'use client';

import { useState } from 'react';

export default function LikeButton({ articleId, initialCount }) {
  // state and event handlers are only available in Client Components
  const [count, setCount] = useState(initialCount);
  const [liked, setLiked] = useState(false);

  function handleClick() {
    if (liked) return;

    // Increment the like count and update the UI immediately (optimistic update)
    setCount(function(prev) { return prev + 1; });
    setLiked(true);

    // Record on the server via the API
    fetch('/api/likes', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ articleId: articleId }),
    });
  }

  return (
    <button onClick={handleClick} disabled={liked}>
      {liked ? '♥ Liked' : '♡ Like'} ({count})
    </button>
  );
}

Usage Notes

Because Server Components run only on the server, browser APIs (window, document, localStorage, etc.) cannot be used. Hooks such as useState, useEffect, and useReducer are also unavailable. Parts that require interactivity or state management must be extracted as Client Components declared with 'use client'.

A Server Component can receive a Client Component as a child element. However, a Client Component cannot directly import a Server Component (passing it via children or props is possible). Also, props passed from a Server Component to a Client Component are limited to serializable values (strings, numbers, arrays, plain objects, etc.). Functions (event handlers) cannot be passed, which requires attention.

Combining with Suspense allows Server Components to be loaded asynchronously while displaying a fallback UI during data fetching. Unlike code splitting with lazy, this approach handles data fetching itself declaratively.

Related pages: Suspense / useState / useEffect / lazy

Common Mistakes

Using useState or useEffect inside a Server Component causes errors

Because Server Components run only on the server, browser-specific features (useState, useEffect, event handlers, etc.) cannot be used. To use these, add the 'use client' directive at the top of the file to convert it to a Client Component.

profile_ng.jsx
// Treated as a Server Component because there is no 'use client'
import { useState } from 'react';

// Using useState in a Server Component causes a build error or runtime error
async function PilotProfile({ id }) {
  const [liked, setLiked] = useState(false);
  const pilot = await fetchPilot(id);

  return (
    <div>
      <h2>{pilot.name}</h2>
      <button onClick={function() { setLiked(true); }}>
        {liked ? 'Favorited' : 'Add to favorites'}
      </button>
    </div>
  );
}

Fixed:

profile_ok.jsx
// Server Component (responsible for data fetching)
async function PilotProfile({ id }) {
  const pilot = await fetchPilot(id);
  return (
    <div>
      <h2>{pilot.name}</h2>
      {/* Separate the interactive part into a Client Component */}
      <LikeButton pilotId={id} />
    </div>
  );
}
like_button.jsx
'use client';

import { useState } from 'react';

// Client Component (responsible for interaction)
function LikeButton({ pilotId }) {
  const [liked, setLiked] = useState(false);
  return (
    <button onClick={function() { setLiked(true); }}>
      {liked ? 'Favorited' : 'Add to favorites'}
    </button>
  );
}

Passing a function as props from a Server Component to a Client Component causes a serialization error

Props passed from a Server Component to a Client Component must be JSON-serializable values. Functions, class instances, and objects with circular references cannot be passed. When a function needs to be used, define it inside the Client Component.

server_ng.jsx
// Server Component
async function ReportPage() {
  // Functions cannot be passed as props to a Client Component
  return <ReportButton onClick={function() { console.log('clicked'); }} />;
}

Fixed:

server_ok.jsx
'use client';

// Define the event handler inside the Client Component
function ReportButton() {
  function handleClick() {
    console.log('clicked');
  }
  return <button onClick={handleClick}>Submit report</button>;
}

If you find any errors or copyright issues, please .