React 服务器组件 (RSC)

文章目录

  • 前言
      • [1. 什么是服务器组件 (Server Components)?](#1. 什么是服务器组件 (Server Components)?)
      • [2. 服务器组件的核心规则](#2. 服务器组件的核心规则)
        • [(1) 异步性 (`async/await`)](#(1) 异步性 (async/await))
        • [(2) 无客户端交互](#(2) 无客户端交互)
        • [(3) 渲染限制](#(3) 渲染限制)
      • [3. 与客户端组件的协作](#3. 与客户端组件的协作)
      • [4. 使用场景](#4. 使用场景)
      • [5. 文件命名约定](#5. 文件命名约定)
      • [6. 常见误区](#6. 常见误区)
      • [7. 示例代码](#7. 示例代码)
      • 关键总结

前言

React 官方文档中 server-components 页面详细解释了 React 服务器组件 (RSC) 的核心概念、规则和使用场景。以下是该页面的核心内容解析:


1. 什么是服务器组件 (Server Components)?

  • 运行环境仅在服务端执行,不会将组件代码(JSX、逻辑、依赖)发送到客户端。
  • 目的
    • 减少客户端 JS 体积,提升加载性能。
    • 直接访问服务端资源(数据库、API、文件系统)。
    • 自动代码分割,避免手动优化。
  • 输出 :将渲染后的 UI 描述(非可交互 JS) 发送给客户端,类似 HTML 流。

2. 服务器组件的核心规则

(1) 异步性 (async/await)
  • 所有服务器组件必须是 async 函数 ,可使用 await 直接获取数据:
js 复制代码
  async function MyServerComponent() {
    const data = await fetchData(); // 直接访问数据库/API
    return <div>{data}</div>;
  }
js 复制代码
    export default async function RootLayout({ children, params }) {
    const resolvedParams = await params;
    const { serializedResources } = await getTranslation(resolvedParams.locale, "common");
    // ...渲染逻辑
  }

这里直接在组件体内用 await 获取服务端数据,然后将数据传递给子组件。

(2) 无客户端交互
  • 禁止使用 Hooks :如 useState, useEffect, useContext 等。
  • 无浏览器 API :无法访问 window, document, localStorage
  • 无事件处理 :不能定义 onClick, onChange 等交互逻辑。

Server Component(服务器组件):

  • 只能在服务器端渲染,不能包含如 useState、useEffect、事件处理(如 onClick)等客户端交互逻辑。
  • 不能访问浏览器 API(如 window、document)。
  • 只能通过 props 向下传递数据,不能响应用户在浏览器中的直接操作。
  • 适合做数据获取、服务端渲染、静态内容输出等。

Client Component(客户端组件):

  • 以 'use client' 开头,可以使用 React 的所有客户端特性(如 useState、useEffect、事件处理等)。
  • 可以访问浏览器 API。
  • 适合做交互、动画、表单、按钮等需要响应用户操作的内容。
(3) 渲染限制
  • 只能返回 可序列化数据客户端组件

    js 复制代码
    // ✅ 合法:传递数据给客户端组件
    function ServerComponent() {
      return <ClientComponent data={...} />;
    }
    
    // ❌ 非法:直接渲染浏览器 API 相关组件
    function InvalidComponent() {
      return <input onChange={...} />; // 事件处理只能在客户端
    }

3. 与客户端组件的协作

组合模式
  • 服务器组件可作为 父组件 渲染客户端组件:
js 复制代码
  // ServerComponent.server.js
  import ClientComponent from './ClientComponent.client';

  export default function ServerComponent() {
    return (
      <div>
        <h1>服务端渲染</h1>
        <ClientComponent /> {/* 嵌套客户端组件 */}
      </div>
    );
  }
html 复制代码
  <I18nProviderWrapper locale={resolvedParams.locale} initialResources={serializedResources}>
    {children}
  </I18nProviderWrapper>

src/components/I18nProviderWrapper.tsx 是一个客户端组件(文件顶部有 'use client'),它被服务器组件 layout.tsx 作为子组件直接渲染。符合 Next.js 推荐的分层架构(Server Component 作为父,Client Component 作为子)

Props 传递规则
  • 传递给客户端组件的 props 必须是 可序列化的
    • ✅ 基本类型:string, number, boolean
    • ✅ 简单对象/数组
    • ✅ JSX(作为 children)
    • ❌ 函数、类实例、Symbol 等不可序列化数据。

4. 使用场景

适合服务器组件 适合客户端组件
数据获取(DB/API) 交互逻辑(表单、动画)
静态内容渲染 使用 Hooks(状态、副作用)
敏感逻辑(访问密钥) 浏览器 API(localStorage)
减少客户端 JS 体积 事件处理(onClick 等)

5. 文件命名约定

  • 服务端组件:*.server.js (或 .server.jsx, .server.tsx)
  • 客户端组件:*.client.js (或 .client.jsx, .client.tsx)
  • 通用组件:无后缀,但需在客户端组件中显式导入。

6. 常见误区

  • 误区 :"服务端组件可替代 SSR"。
    • 纠正 :RSC 与 SSR 互补:
      • SSR:将客户端组件初始 HTML 快速渲染到浏览器。
      • RSC:在服务端生成静态内容,减少客户端负担。
  • 误区 :"服务器组件可处理用户交互"。
    • 纠正:交互必须交给客户端组件处理。

7. 示例代码

服务端组件(获取数据):
js 复制代码
// ProductDetails.server.js
async function ProductDetails({ id }) {
  const product = await db.products.get(id); // 直接访问数据库
  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      <ProductImage image={product.image} /> {/* 客户端组件 */}
    </div>
  );
}
客户端组件(处理交互):
js 复制代码
// ProductImage.client.js
'use client'; // 标记为客户端组件

function ProductImage({ image }) {
  const [zoomed, setZoomed] = useState(false);
  return (
    <img 
      src={image.url} 
      onClick={() => setZoomed(!zoomed)}
      className={zoomed ? 'zoomed' : ''}
    />
  );
}

关键总结

特性 服务器组件 客户端组件
执行环境 服务端 浏览器
数据获取 直接访问后端资源 通过 fetch/API 调用
交互性 ❌ 无事件处理/状态 ✅ 支持所有交互逻辑
代码发送到客户端 ❌ 仅发送渲染结果 ✅ 发送完整 JS 代码
减少 JS 体积 ✅ 显著优化 ❌ 增加客户端负担

通过合理组合 Server Components(内容) + Client Components(交互),可构建高性能的 React 应用。建议结合 Next.js App Router 实践以体验完整 RSC 工作流。

相关推荐
jin1233221 分钟前
React Native鸿蒙跨平台完成剧本杀组队详情页面,可以复用桌游、团建、赛事等各类组队详情页开发
javascript·react native·react.js·ecmascript·harmonyos
李白你好3 分钟前
Burp Suite插件用于自动检测Web应用程序中的未授权访问漏洞
前端
宴之敖者、23 分钟前
Linux——\r,\n和缓冲区
linux·运维·服务器
LuDvei24 分钟前
LINUX错误提示函数
linux·运维·服务器
未来可期LJ31 分钟前
【Linux 系统】进程间的通信方式
linux·服务器
心理之旅42 分钟前
高校文献检索系统
运维·服务器·容器
Lenyiin1 小时前
Linux 基础IO
java·linux·服务器
The Chosen One9851 小时前
【Linux】深入理解Linux进程(一):PCB结构、Fork创建与状态切换详解
linux·运维·服务器
刘一说1 小时前
Vue 组件不必要的重新渲染问题解析:为什么子组件总在“无故”刷新?
前端·javascript·vue.js
jin1233221 小时前
基于React Native鸿蒙跨平台移动端表单类 CRUD 应用,涵盖地址列表展示、新增/编辑/删除/设为默认等核心操作
react native·react.js·ecmascript·harmonyos