本章讨论新版 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/组件与渲染分支。