Skip to main content

客户端组件

客户端组件允许您编写可以在请求时在客户端上呈现的交互式UI。 在Next.js中,客户端渲染是可选择的(opt-in), 这意味着您必须明确决定React应在客户端上渲染哪些组件。

本页面将介绍客户端组件的工作原理、它们是如何渲染的以及何时使用它们。

客户端渲染的好处

在客户端进行渲染工作有一些好处,包括:

  • 互动性:客户端组件可以使用状态、效果和事件侦听器,这意味着它们可以为用户提供即时反馈并更新UI。
  • 浏览器API:客户端组件可以访问浏览器API, 如地理位置localStorage,使您能够为特定用例构建UI。

在Next.js中使用客户端组件

要使用客户端组件, 您可以在文件的顶部(在导入之前)添加React的"use client"指令。

"use client"用于声明服务器和客户端组件模块之间的边界。 这意味着通过在文件中定义"use client",导入到该文件的所有其他模块,包括子组件,都被视为客户端捆绑的一部分。

app/counter.tsx
'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>
)
}

下面的图示显示,如果未定义"use client"指令,则在嵌套组件(toggle.js)中使用onClickuseState会导致错误。 这是因为默认情况下,在服务器上渲染组件,这些API是不可用的。 通过在toggle.js中定义"use client"指令, 您可以告诉React在客户端上渲染组件及其子组件,其中这些API是可用的。

use client directive

定义多个"use client"入口点:

您可以在React组件树中定义多个"use client"入口点。这允许您将应用程序拆分为多个客户端捆绑包(或分支)。

但是,并不需要在每个需要在客户端上渲染的组件中定义"use client"。一旦定义了边界,所有子组件和导入到其中的模块都被视为客户端捆绑的一部分。

客户端组件是如何渲染的?

在Next.js中,客户端组件的渲染方式取决于请求是属于完整页面加载(对应应用程序的初始访问或浏览器刷新触发的页面重新加载)还是后续导航的一部分。

完整页面加载

为了优化初始页面加载,Next.js将使用React的API在服务器上为客户端和服务器组件渲染静态HTML预览。这意味着当用户首次访问您的应用程序时,他们将立即看到页面的内容,而无需等待客户端下载、解析和执行客户端组件JavaScript捆绑包。

在服务器上:

  1. React将服务器组件渲染为一种称为React服务器组件负载(RSC Payload)的特殊数据格式,其中包括对客户端组件的引用。
  2. Next.js使用RSC Payload和客户端组件JavaScript指令在服务器上为路由渲染HTML。

然后,在客户端上:

  1. 使用HTML可以立即显示路由的快速非交互式初始预览。
  2. 使用React服务器组件负载来协调客户端和服务器组件树,并更新DOM。
  3. 使用JavaScript指令来使客户端组件水合 并使其UI可交互。

什么是水合?

水合是将事件侦听器附加到DOM的过程,以使静态HTML变得可交互。在幕后, 水合是使用hydrateRoot React API完成的。

后续导航

在后续导航中,客户端组件完全在客户端上渲染,无需服务器渲染的HTML。

这意味着将下载并解析客户端组件JavaScript捆绑包。 一旦捆绑包准备好,React将使用RSC Payload来协调客户端和服务器组件树,并更新DOM。

返回服务器环境

有时,在声明了"use client"边界之后,您可能希望回到服务器环境。 例如,您可能希望减小客户端捆绑包大小、在服务器上获取数据或使用仅在服务器上可用的API。

即使嵌套在客户端组件内,您仍然可以将代码保留在服务器上,方法是交错使用客户端和服务器组件以及 服务器操作。 有关更多信息, 请参见Composition Patterns页面。