首页 / React 19 入门教程 / Server Components 简介

React 19 入门教程

Server Components 简介

本教程共 50 篇 · 第 47 篇 · 更新于 2026-07-29 · 约 10 分钟阅读

ReactServer ComponentsRSCServer ActionsSSRReact 19

47. Server Components 简介

本节目标:理解 Server Components 是什么、和 SSR 有什么区别、什么时候该用哪一种。

RSC 解决什么问题

传统的 React 应用,所有组件都在浏览器里运行。

这意味着用户要下载所有组件的 JS,包括那些只负责”展示数据、不需要交互”的组件。

Server Components(RSC)是一种新组件类型:它在服务器上运行,只把渲染结果发给客户端。

传统模式

// 客户端组件:所有 JS 都要下载
function Article({ id }) {
  const [article, setArticle] = useState(null);

  useEffect(() => {
    fetch(`/api/articles/${id}`).then(/* ... */);
  }, [id]);

  return (
    <article>
      <h1>{article.title}</h1>
      <Author id={article.authorId} />  <!-- 又触发一次请求 -->
      <p>{article.content}</p>
    </article>
  );
}

问题:JS 包大、请求瀑布(组件套组件地发请求)、重复的 JSON 序列化。

RSC 模式

// Server Component:在服务器上运行,直接读数据库
import db from './database';

async function Article({ id }) {
  const article = await db.articles.get(id);
  const author = await db.authors.get(article.authorId);

  return (
    <article>
      <h1>{article.title}</h1>
      <span>作者:{author.name}</span>
      <p>{article.content}</p>
    </article>
  );
}

优势:零客户端 JS、直接访问数据源、没有请求瀑布。

三种组件类型

React 19 把组件分成三类:

类型运行环境能做什么指令
Server Component服务器读文件、查数据库、渲染 UI默认(无指令)
Client Component浏览器useState、useEffect、事件处理"use client"
共享组件两者皆可根据导入位置决定
Note

没有指令的组件默认是 Server Component。这不是 Next.js 才有的,是 React 19 的标准。但需要注意:Server Components 需要框架支持(如 Next.js App Router、Remix 等)才能使用。纯客户端 React 项目(如仅用 Vite 搭建的项目)无法直接使用 Server Components。

两个指令

"use client" — 声明客户端组件

"use client";

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

一个文件顶部加了 "use client",整个文件及其导入的所有组件都会变成客户端组件。

"use server" — 声明 Server Action

"use server";

import db from './database';

export async function createNote() {
  await db.notes.create();
}

export async function deleteNote(id) {
  await db.notes.delete(id);
}

"use server" 标记的函数在客户端调用时,React 会自动发请求到服务器执行。

Warning

"use server" 不是声明 Server Component 的!Server Component 没有指令。"use server" 用于 Server Actions。

组合模式

实际开发中,Server Component 和 Client Component 是嵌套使用的。

// 📄 ArticlePage.jsx(Server Component)
import db from './database';
import { LikeButton } from './LikeButton';

async function ArticlePage({ id }) {
  const article = await db.articles.get(id);

  return (
    <article>
      <h1>{article.title}</h1>
      <p>{article.content}</p>
      {/* 👇 客户端组件嵌套在服务端组件里 */}
      <LikeButton articleId={id} initialLikes={article.likes} />
    </article>
  );
}
// 📄 LikeButton.jsx(Client Component)
"use client";

import { useState } from 'react';

export function LikeButton({ articleId, initialLikes }) {
  const [likes, setLikes] = useState(initialLikes);

  async function handleLike() {
    const newLikes = await fetch(`/api/like`, {
      method: 'POST',
      body: JSON.stringify({ articleId })
    });
    setLikes(await newLikes.json());
  }

  return <button onClick={handleLike}>点赞 {likes}</button>;
}

规则:

  • Server Component 可以导入 Client Component
  • Client Component 不能导入 Server Component(因为服务器代码不能发到浏览器)
  • Server Component 可以把 Server Component 作为 children 传给 Client Component

Server Actions

Server Actions 让客户端组件能调用服务器上的函数。

基本用法

在 Server Component 内定义:

// 📄 NoteList.jsx(Server Component)
import Button from './Button';

function NoteList() {
  async function createNoteAction() {
    "use server";           // 标记为 Server Action
    await db.notes.create();
  }

  return <Button onClick={createNoteAction}>新建笔记</Button>;
}

作为独立模块:

// 📄 actions.js
"use server";

export async function createNote() {
  await db.notes.create();
}

export async function deleteNote(id) {
  await db.notes.delete(id);
}
// 📄 NoteList.jsx
"use client";

import { createNote, deleteNote } from './actions';

function NoteList() {
  return (
    <>
      <button onClick={createNote}>新建</button>
      <button onClick={() => deleteNote(1)}>删除</button>
    </>
  );
}

调用 createNote() 时,React 会在后台发请求到服务器。你不需要写 fetch

表单直接绑定

Server Action 可以传给 <form action={...}>

"use client";

import { updateName } from './actions';

function UpdateName() {
  return (
    <form action={updateName}>
      <input type="text" name="name" />
      <button type="submit">更新</button>
    </form>
  );
}

提交表单时 React 自动调 updateName(formData),不需要 onSubmit

与 SSR 的区别

很多人搞混 RSC 和 SSR。它们是完全不同的东西:

维度SSRRSC
运行时机请求时/构建时构建时或请求时
输出HTML序列化组件树(RSC Payload)
JS Bundle包含所有组件只包含客户端组件
交互注水后全部可交互服务端组件始终不可交互
重新获取刷新整个页面只重新请求变化的组件

SSR 和 RSC 可以组合使用:服务器组件渲染成 RSC Payload,再通过 SSR 转成 HTML。

什么时候用哪个

用 Server Component 的场景:

  • 展示数据(读数据库、调 API)
  • 渲染静态内容(markdown、文档)
  • 不需要交互的 UI(列表、卡片、布局)

用 Client Component 的场景:

  • 有交互(点击、输入、切换)
  • 使用浏览器 API(localStorage、navigator)
  • 使用 useState/useEffect
Tip

经验法则:能用 Server Component 的就用,只在”必须交互”的地方加 "use client"

限制

Server Component 的限制要记住:

  • 不能用 useStateuseEffectuseReducer 等客户端 Hook
  • 不能用 onClick 等事件处理
  • 不能用浏览器专属 API
  • 可以直接 await 异步数据(async/await 组件)
  • 可以访问服务器资源(数据库、文件系统)
// ✅ 正确:Server Component 里直接 await
async function Page() {
  const data = await db.query();
  return <div>{data}</div>;
}

// ❌ 错误:Server Component 里用 useState
function Page() {
  const [data, setData] = useState(null);  // 报错!
  // ...
}

小结

  • Server Components 在服务器运行,不打包 JS 到客户端
  • 默认无指令就是 Server Component
  • "use client" 声明客户端组件
  • "use server" 声明 Server Action(不是声明 Server Component)
  • RSC 和 SSR 是独立的概念,可以组合
  • 优先用 Server Component,只在需要交互时切到 Client Component