组件与渲染

772
2023/06/17 13:22:57

本章讨论新版 Next.js 中变化最大的部分:组件和渲染。

之前版本的组件

在之前版本中:

  • 不太严谨地说:除非你使用了 getServerSideProps(),否则可以视为客户端组件和客户端渲染(当然还可能是其它渲染,通过 getXXProps()
  • 可以在组件中直接使用 React 的 useState()useEffect() 等 hook

服务端组件

现在 Next.js 默认所有组件都是服务端组件:

  • 无须使用 getServerSideProps(),默认就是服务端渲染
  • 无法使用 React 的 useState()useEffect() 等 hook
  • 可以异步获取远程数据

客户端组件

  • 需要使用 "use client" 语句声明该组件是客户端组件
  • 可以使用 React 的 useState()useEffect() 等 hook
  • Next.js 的约定中,有一些是必须是客户端组件

案例:获取IP

我们分别编写服务端组件和客户端组件来通过https://httpbin.org/ip来获取IP。

客户端组件

"use client";

import React, { useEffect, useState } from "react";

export default function IPClient() {
  const [ip, setIp] = useState("正在获取");
  useEffect(() => {
    fetch("https://httpbin.org/ip")
      .then((res) => res.json())
      .then((data) => {
        setIp(data.origin);
      })
      .catch((e) => {
        console.log(e);
        setIp(`获取失败,请重试`);
      });
  }, []);
  return <div>客户端组件获取到的IP:{ip}</div>;
}
  • "use client";:告诉 Next.js ,这是一个客户端组件
  • 使用 useState() 来维护ip数据
  • useEffect() 中,通过 fetch() 从远程API中获取数据
  • 客户端组件中的 fetch() 是由浏览器提供的

服务端组件

  • 无须特别声明,在 Next.js 所有组件默认都是服务端组件
  • 可以使用 await
  • 服务端组件中的 fetch() 是由 Next.js 提供的

入口文件

import { IPClient, IPServer } from "@/components/Ip";
import Link from "next/link";

export default function Home({ searchParams }) {
  const isClientStr = searchParams.client || "";
  const isClient = isClientStr === "1";
  return (
    <>
      {isClient ? <IPClient /> : <IPServer />}

      <div style={{ display: "flex", gap: "1rem" }}>
        <Link href="/">服务端组件</Link>
        <Link href="/?client=1">客户端组件</Link>
      </div>
    </>
  );
}

本章代码位于03/组件与渲染分支。