客户端组件
客户端组件允许你编写交互式 UI,该 UI 在服务端预渲染,并且可以使用客户端 JavaScript 在浏览器中运行。
本页将介绍客户端组件的工作原理、渲染方式以及何时可以使用它们。
客户端渲染的优势
在客户端进行渲染工作有几个好处,包括
- 交互性:客户端组件可以使用状态、效果和事件监听器,这意味着它们可以为用户提供即时反馈并更新 UI。
- 浏览器 API:客户端组件可以访问浏览器 API,例如 地理位置 或 localStorage。
在 Next.js 中使用客户端组件
要使用客户端组件,你可以将 React "use client"
指令 添加到文件的顶部,在你的导入语句之上。
"use client"
用于声明服务端和客户端组件模块之间的边界。这意味着通过在文件中定义 "use client"
,所有导入到该文件中的其他模块,包括子组件,都被视为客户端 bundle 的一部分。
'use client'
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
)
}
下图显示,如果在嵌套组件 (toggle.js
) 中使用 onClick
和 useState
,并且未定义 "use client"
指令,则会导致错误。这是因为,默认情况下,App Router 中的所有组件都是服务端组件,这些 API 在服务端组件中不可用。通过在 toggle.js
中定义 "use client"
指令,你可以告诉 React 进入客户端边界,在该边界中这些 API 是可用的。


定义多个
use client
入口点:你可以在你的 React 组件树中定义多个 "use client" 入口点。这允许你将你的应用程序拆分为多个客户端 bundle。
但是,
"use client"
不需要定义在每个需要在客户端渲染的组件中。一旦你定义了边界,所有子组件和导入到其中的模块都被视为客户端 bundle 的一部分。
客户端组件是如何渲染的?
在 Next.js 中,客户端组件的渲染方式取决于请求是完整页面加载(首次访问你的应用程序或浏览器刷新触发的页面重新加载)的一部分还是后续导航。
完整页面加载
为了优化初始页面加载,Next.js 将使用 React 的 API 在服务端为客户端和服务端组件渲染静态 HTML 预览。这意味着,当用户首次访问你的应用程序时,他们将立即看到页面内容,而无需等待客户端下载、解析和执行客户端组件 JavaScript bundle。
在服务端
- React 将服务端组件渲染为一种特殊的数据格式,称为 React 服务端组件 Payload (RSC Payload),其中包括对客户端组件的引用。
- Next.js 使用 RSC Payload 和客户端组件 JavaScript 指令来在服务端渲染路由的 HTML。
然后在客户端
- HTML 用于立即显示路由的快速非交互式初始预览。
- React 服务端组件 Payload 用于协调客户端和服务端组件树,并更新 DOM。
- JavaScript 指令用于 hydration 客户端组件并使其 UI 具有交互性。
什么是 hydration?
Hydration 是将事件监听器附加到 DOM 的过程,以使静态 HTML 具有交互性。在幕后,hydration 是使用
hydrateRoot
React API 完成的。
后续导航
在后续导航中,客户端组件完全在客户端渲染,而没有服务端渲染的 HTML。
这意味着客户端组件 JavaScript bundle 会被下载和解析。一旦 bundle 准备就绪,React 将使用 RSC Payload 来协调客户端和服务端组件树,并更新 DOM。
返回服务端环境
有时,在你声明了 "use client"
边界之后,你可能想要返回到服务端环境。例如,你可能想要减小客户端 bundle 大小、在服务端获取数据,或者使用仅在服务端可用的 API。
即使代码理论上嵌套在客户端组件内部,你也可以通过交错客户端和服务端组件和服务端 Actions 将代码保留在服务端。有关更多信息,请参阅组合模式页面。
这有帮助吗?