Client Components 客户端组件

Client Components allow you to write interactive UI that can be rendered on the client at request time. In Next.js, client rendering is opt-in, meaning you have to explicitly decide what components React should render on the client.

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

This page will go through how Client Components work, how they're rendered, and when you might use them.

本页将介绍客户端组件的工作原理、它们的渲染方式以及您可能使用它们的情况。

1.Benefits of Client Rendering 客户端渲染的优势

There are a couple of benefits to doing the rendering work on the client, including:

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

  • Interactivity: Client Components can use state, effects, and event listeners, meaning they can provide immediate feedback to the user and update the UI.
    交互性:客户端组件可以使用状态、效果和事件监听器,这意味着它们可以向用户提供即时反馈并更新 UI。

  • Browser APIs: Client Components have access to browser APIs, like geolocation or localStorage, allowing you to build UI for specific use cases.
    浏览器 API:客户端组件可以访问浏览器 API,例如地理位置或 localStorage,从而允许您针对特定用例构建 UI。

2.Using Client Components in Next.js 在 Next.js 中使用客户端组件

To use Client Components, you can add the React "use client" directive at the top of a file, above your imports.

要使用客户端组件,您可以在文件顶部添加 React "use client" 指令,位于导入内容上方。

"use client" is used to declare a boundary between a Server and Client Component modules. This means that by defining a "use client" in a file, all other modules imported into it, including child components, are considered part of the client bundle.

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

'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>
  )
}

The diagram below shows that using onClick and useState in a nested component (toggle.js) will cause an error if the "use client" directive is not defined. This is because, by default, the components are rendered on the server where these APIs are not available. By defining the "use client" directive in toggle.js, you can tell React to render the component and its children on the client, where the APIs are available.

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

Defining multiple use client entry points:
定义多个 use client 入口点:

You can define multiple "use client" entry points in your React Component tree. This allows you to split your application into multiple client bundles (or branches).
您可以在 React 组件树中定义多个“use client”入口点。这允许您将应用程序拆分为多个客户端包(或分支)。

However, "use client" doesn't need to be defined in every component that needs to be rendered on the client. Once you define the boundary, all child components and modules imported into it are considered part of the client bundle.
然而, "use client" 不需要在每个需要在客户端渲染的组件中定义。一旦您定义了边界,导入其中的所有子组件和模块都被视为客户端包的一部分。

3.How are Client Components Rendered? 客户端组件如何渲染?

In Next.js, Client Components are rendered differently depending on whether the request is part of a full page load (an initial visit to your application or a page reload triggered by a browser refresh) or a subsequent navigation.

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

a. Full page load 整页加载

To optimize the initial page load, Next.js will use React's APIs to render a static HTML preview on the server for both Client and Server Components. This means, when the user first visits your application, they will see the content of the page immediately, without having to wait for the client to download, parse, and execute the Client Component JavaScript bundle.

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

On the server: 在服务器上:

-React renders Server Components into a special data format called the React Server Component Payload (RSC Payload), which includes references to Client Components.

React 将服务器组件呈现为一种称为 React 服务器组件负载 (RSC 负载) 的特殊数据格式,其中包括对客户端组件的引用。

-Next.js uses the RSC Payload and Client Component JavaScript instructions to render HTML for the route on the server.

Next.js 使用 RSC 负载和客户端组件 JavaScript 指令在服务器上呈现路由的 HTML。

Then, on the client:

然后,在客户端:

-The HTML is used to immediately show a fast non-interactive initial preview of the route.

HTML 用于立即显示路由的快速非交互式初始预览。

-The React Server Components Payload is used to reconcile the Client and Server Component trees, and update the DOM.

React 服务器组件负载用于协调客户端和服务器组件树,并更新 DOM。

-The JavaScript instructions are used to hydrate Client Components and make their UI interactive.

JavaScript 指令用于激活客户端组件并使其 UI 具有交互性。

What is hydration? 水合作用是什么?

Hydration is the process of attaching event listeners to the DOM, to make the static HTML interactive. Behind the scenes, hydration is done with the hydrateRoot React API.
水合是将事件侦听器附加到 DOM 的过程,以使静态 HTML 具有交互性。在幕后,水合是使用 hydrateRoot React API 完成的。

b.Subsequent Navigations 后续导航

On subsequent navigations, Client Components are rendered entirely on the client, without the server-rendered HTML.

在后续导航中,客户端组件完全在客户端呈现,而无需服务器呈现的 HTML。

This means the Client Component JavaScript bundle is downloaded and parsed. Once the bundle is ready, React will use the RSC Payload to reconcile the Client and Server Component trees, and update the DOM.

这意味着客户端组件 JavaScript 包已下载并解析。一旦包准备就绪,React 将使用 RSC 有效载荷协调客户端和服务器组件树,并更新 DOM。

4.Going back to the Server Environment 返回服务器环境

Sometimes, after you've declared the "use client" boundary, you may want to go back to the server environment. For example, you may want to reduce the client bundle size, fetch data on the server, or use an API that is only available on the server.

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

You can keep code on the server even though it's theoretically nested inside Client Components by interleaving Client and Server Components and Server Actions. See the Composition Patterns page for more information.

即使理论上嵌套在客户端组件中,您也可以通过交错客户端和服务器组件以及服务器操作来将代码保留在服务器上。有关更多信息,请参阅组合模式页面。