Back

Next.js 系列 05:什么是服务器组件

Published on 5th September 2024

React 服务器组件,英文 React Server Components,本系列文章简称 RSC。

最直接的方法是通过对比代码入手。我们将上一篇开头部分的代码进行改写。 前:

// pages/index.jsx

export const getServerSideProps = async () => {
  const module1 = await fetch('/api/module1').then((resp) => resp.json());
  const module2 = await fetch('/api/module2').then((resp) => resp.json());

  return { props: { module1, module2 } };
};

export default function Home({ module1, module2 }) {
  return (
    <main>
      <Module1 data={module1} />
      <Module2 data={module2} />
    </main>
  );
}

后:

// app/page.jsx

export default function Home() {
  return (
    <main>
      <Module1 />
    </main>
  );
}

async function Module1() {
  const data = await fetch('/api/module1').then((resp) => resp.json());

  return (
    <div>
      {JSON.stringify(data)}
    </div>
  );
}
注:先将 Pages Router 改写为 App Router。做迁移不是本文的目的,最简单的方法是新建一个 Next 项目。

一切变得新鲜起来。可以在 Component 中请求 API 获取渲染数据。如果你有 PHP Template 的开发经验,或许会觉得有些亲切。 RSC 的重要思想是它们仅在服务器上运行。它们永远不会在客户端上 Hydrate,旨在用于不需要交互的组件。

在 React 的服务器范例中,我们需要声明一个组件是服务器组件还是客户端组件,可以使用“指令”做到这一点:

'use client' // 表示客户端组件

import React from 'react';

function Counter() {
  const [count, setCount] = React.useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      count: {count}
    </button>
  );
}

文件头添加了一行 ‘use client’,如果你以前没见过这种东西,看起来有点疑惑。该约定来自 ‘use strict’,该指令收紧了 JavaScript 中的一些规则,React 团队重新使用了这个约定。

理论上 RSC 需要添加 ‘use server’,但在 Next.js 中,所有组件都被假定为 RSC,因此可以省略它。

RSC 特点和限制

作为一种新型组件,RSC 的特点如下:

  1. 仅在服务器上运行
  2. 不会在客户端上 Hydrate
  3. 不会重新渲染(即使状态发生改变,也不会重新渲染)

限制如下:

  1. 无法使用 state
  2. 无法使用 context
  3. 无法使用 effect

疑问:既然无法使用 state,为什么说状态发生改变,不会重新渲染?
先卖个关子,我想把这部分单独写成一小节,此刻你只需记住该特点就够了。

如果你尝试在 RSC 上使用 state,会得到错误 useState only works in Client Components.

// app/page.tsx

import React from "react";

export default function Home() {
  React.useState(0);

  return <main></main>;
}

RSC-state-error

下一篇,我们来看 RSC 的优点。