6月2日 23:11

React Server Components 是什么?和 Client Components 怎么配合?

React Server Components(RSC)是只在服务端渲染的组件——它们的代码不会发送到浏览器。这是 React 架构的根本变化:组件不再默认跑在客户端,而是默认跑在服务端。

RSC 解决什么问题

传统 React 应用把所有组件代码打包成 JS 发给浏览器。一个列表页可能有 200KB 的 JS,但大部分是数据获取和渲染逻辑,用户交互只占一小部分。用户要等 JS 下载、解析、执行完才能看到页面。

RSC 的解决方案:数据获取和渲染在服务端完成,只把 HTML 和少量交互代码发给浏览器。结果:更快的首屏、更小的 JS 包、更简单的数据获取。

Server Component vs Client Component

tsx
// Server Component(默认)— 不发 JS 给浏览器 async function ArticleList() { const articles = await db.article.findMany(); // 直接查数据库 return ( <ul> {articles.map(a => <li key={a.id}>{a.title}</li>)} </ul> ); } // Client Component — JS 会发给浏览器 'use client' import { useState } from 'react'; function SearchBox() { const [query, setQuery] = useState(''); // 需要状态 return <input value={query} onChange={e => setQuery(e.target.value)} />; }

判断标准很简单:需要 useStateuseEffectonClick 等 React hooks/事件的就是 Client Component,否则就是 Server Component。

数据获取方式的变化

Pages Router 时代,客户端获取数据:

tsx
// Pages Router — 客户端获取 useEffect(() => { fetch('/api/articles').then(r => r.json()).then(setArticles); }, []);

App Router + RSC,服务端直接获取:

tsx
// App Router — 服务端获取 async function Page() { const articles = await db.article.findMany(); return <ArticleList articles={articles} />; }

不需要 API 路由,不需要 loading 状态管理,不需要客户端缓存。服务端拿到数据直接渲染成 HTML。

组合模式

Server Component 可以渲染 Client Component,但反过来不行:

tsx
// Server Component import SearchBox from './SearchBox'; // Client Component async function Page() { const data = await fetchData(); return ( <div> <SearchBox /> {/* Client Component:交互 */} <ArticleList data={data} /> {/* Server Component:展示 */} </div> ); }

关键规则:

  • Server Component 可以 import 和渲染 Client Component
  • Client Component 不能 import Server Component
  • Server Component 可以通过 props 把数据传给 Client Component(必须是可序列化的数据)

什么时候用 Client Component

只有这四种情况需要 'use client'

  1. 需要交互(onClick、onChange)
  2. 需要状态(useState、useReducer)
  3. 需要生命周期(useEffect)
  4. 需要浏览器 API(window、localStorage)

其他都用 Server Component。一个常见错误:因为不熟悉 RSC 而给所有组件加 'use client'——这样 App Router 就退化成了 Pages Router,失去了 RSC 的性能优势。

RSC 的局限

  • Server Component 不能用 hooks(useState、useEffect)
  • Server Component 不能用浏览器 API(window、document)
  • Server Component 传给 Client Component 的 props 必须可序列化(不能传函数、类实例)
  • 调试更难——错误堆栈跨服务端和客户端

RSC 仍然在快速演进,API 可能在未来版本变化。但方向是明确的:服务端渲染更多,客户端 JS 更少。

标签:Next.js