跳至内容

10

服务器组件和客户端组件

要了解服务器组件和客户端组件的工作原理,熟悉两个基础的 Web 概念非常有帮助。

  • 您的应用程序代码可以执行的环境:服务器和客户端。
  • 将服务器和客户端代码分隔开的网络边界

服务器和客户端环境

在 Web 应用程序的上下文中

Diagram showing a browser on the left and a server on the right, separated by a network boundary.
  • 客户端指的是用户设备上的浏览器,它向服务器发送请求以获取您的应用程序代码。然后,它将从服务器接收到的响应转换为用户可以交互的界面。
  • 服务器指的是数据中心中的计算机,它存储您的应用程序代码,接收来自客户端的请求,执行一些计算,并发送回相应的响应。

每个环境都有自己的一套功能和约束。例如,通过将渲染和数据获取转移到服务器,您可以减少发送到客户端的代码量,从而提高应用程序的性能。但是,正如您之前了解到的,要使您的 UI 具有交互性,您需要更新客户端上的 DOM。

因此,您为服务器和客户端编写的代码并不总是相同的。某些操作(例如数据获取或管理用户状态)更适合于一个环境而不是另一个环境。

网络边界

网络边界是分隔不同环境的概念线。

在 React 中,您可以选择在组件树中放置网络边界的位置。例如,您可以在服务器上获取数据并渲染用户的帖子(使用服务器组件),然后在客户端上渲染每个帖子的交互式LikeButton(使用客户端组件)。

同样,您可以创建一个在服务器上渲染并在页面之间共享的Nav组件,但是如果您想显示链接的活动状态,则可以在客户端上渲染Links列表。

A component tree showing a layout that has 3 components as its children: Nav, Page, and Footer. The page component has 2 children: Posts and LikeButton. The Posts component is rendered on the server, and the LikeButton component is rendered on the client.

在幕后,组件被分成两个模块图。服务器模块图(或树)包含在服务器上渲染的所有服务器组件,而客户端模块图(或树)包含所有客户端组件。

服务器组件渲染后,一种称为React 服务器组件有效负载 (RSC)的特殊数据格式将发送到客户端。RSC 有效负载包含

  1. 服务器组件的渲染结果。
  2. 客户端组件应渲染位置的占位符(或空洞)及其 JavaScript 文件的引用。

React 使用此信息来整合服务器组件和客户端组件,并在客户端上更新 DOM。

让我们看看它是如何工作的。

使用客户端组件

正如您在上一章中学到的,Next.js 默认使用服务器组件 - 这是为了提高应用程序的性能,这意味着您无需采取其他步骤即可采用它们。

回顾浏览器中的错误,Next.js 警告您正在尝试在服务器组件内部使用useState。您可以通过将交互式“喜欢”按钮移动到客户端组件来解决此问题。

app文件夹内创建一个名为like-button.js的新文件,该文件导出一个LikeButton组件。

/app/like-button.js
export default function LikeButton() {}

<button>元素和handleClick()函数从page.js移动到新的LikeButton组件。

/app/like-button.js
export default function LikeButton() {
  function handleClick() {
    setLikes(likes + 1);
  }
 
  return <button onClick={handleClick}>Like ({likes})</button>;
}

接下来,移动likes状态和导入。

/app/like-button.js
import { useState } from 'react';
 
export default function LikeButton() {
  const [likes, setLikes] = useState(0);
 
  function handleClick() {
    setLikes(likes + 1);
  }
 
  return <button onClick={handleClick}>Like ({likes})</button>;
}

现在,要使LikeButton成为客户端组件,请在文件顶部添加 React 'use client'指令。这告诉 React 在客户端上渲染组件。

/app/like-button.js
'use client';
 
import { useState } from 'react';
 
export default function LikeButton() {
  const [likes, setLikes] = useState(0);
 
  function handleClick() {
    setLikes(likes + 1);
  }
 
  return <button onClick={handleClick}>Like ({likes})</button>;
}

回到您的page.js文件中,将LikeButton组件导入到您的页面中。

/app/page.js
import LikeButton from './like-button';
 
function Header({ title }) {
  return <h1>{title ? title : 'Default title'}</h1>;
}
 
export default function HomePage() {
  const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];
 
  return (
    <div>
      <Header title="Develop. Preview. Ship." />
      <ul>
        {names.map((name) => (
          <li key={name}>{name}</li>
        ))}
      </ul>
      <LikeButton />
    </div>
  );
}

保存这两个文件并在浏览器中查看您的应用程序。现在没有错误了,一旦您进行更改并保存,您应该会注意到浏览器会自动更新以反映更改。

此功能称为快速刷新。它为您对所做任何编辑提供了即时反馈,并与 Next.js 预先配置。

总结

概括地说,您学习了服务器和客户端环境以及何时使用每个环境。您还了解到 Next.js 默认使用 React 服务器组件来提高性能,以及如何选择使用客户端组件来使 UI 的较小部分具有交互性。

其他阅读资料

关于服务器组件和客户端组件,还有很多内容需要学习。以下是一些其他资源。

您已完成本章10

您已学习如何使用服务器组件和客户端组件。

下一步

11:后续步骤

接下来做什么?