agentmentoragentmentor

第 06 节:什么时候才需要浏览器交互

本节 objectives:

  • 能区分 Server Component 和 Client Component 的使用场景。
  • 能用 "use client"、事件处理、useState 做一个小交互。
  • 能避免把整页都无脑改成 Client Component。

先修:会写组件、props、样式 | 上一节 << 05 | 下一节 07 >>

不是所有组件都应该搬到浏览器里

Next.js App Router 默认偏向 Server Components。它们可以在服务器上渲染,减少发送到浏览器的 JavaScript。需要点击、输入、状态、浏览器 API 时,才使用 Client Components。Next.js 官方文档把 "use client" 作为客户端组件入口边界来说明1

这对新手很重要:你不是看到报错就把全站都加 "use client"。你要学会把需要交互的小块切出来,其他页面内容继续留在服务器侧。

讲解

Server Component 适合静态展示和服务端数据。
页面标题、文章列表、从服务器拿到的数据展示,通常可以先写成 Server Component。它们不需要浏览器里的状态。

Client Component 适合用户动作。
点击按钮展开内容、输入框实时过滤、计数器,都需要浏览器响应事件。React 官方把事件处理和状态分别作为交互基础讲解23

useState 保存组件记忆。
useState 返回当前状态和更新它的函数。用户点击按钮时调用更新函数,React 重新渲染这块界面3

边界越小越清楚。
如果只有一个按钮需要交互,就把按钮相关组件设为 Client Component,再从 Server Component 页面里引用它。这样学习和调试都更容易。

跟我做一遍(worked example)

目标:在首页加入一个「显示/隐藏学习提示」按钮。

  1. 新建 app/TipToggle.tsx:
tsx
"use client";
import { useState } from "react";
export default function TipToggle() {  const [open, setOpen] = useState(false);
  return (    <section>      <button onClick={() => setOpen(!open)}>        {open ? "收起提示" : "显示提示"}      </button>      {open ? <p>每次只改一个文件,更容易知道错误从哪里来。</p> : null}    </section>  );}
  1. app/page.tsx 里使用它:
tsx
import TipToggle from "./TipToggle";
export default function Home() {  return (    <main>      <h1>Next.js 学习记录</h1>      <TipToggle />    </main>  );}

为什么这样写:

  • "use client" 只放在需要交互的 TipToggle 文件顶部。
  • open 记录当前是否展开。
  • onClick 是事件处理器。
  • Home 不需要自己变成 Client Component。

换你补全(faded example)

下面要做一个「已完成/未完成」按钮。补全状态初始值、点击更新和显示文字。

tsx
"use client";
import { useState } from "react";
export default function DoneButton() {  const [done, setDone] = useState(______);
  return (    <button onClick={() => setDone(______)}>      {done ? "______" : "______"}    </button>  );}

参考答案:

tsx
"use client";
import { useState } from "react";
export default function DoneButton() {  const [done, setDone] = useState(false);
  return (    <button onClick={() => setDone(!done)}>      {done ? "已完成" : "标记完成"}    </button>  );}

关键判断点:done 是布尔值;点击时用 !done 翻转;显示文字根据状态变化。

小结 + 通向下一节

你已经能做最小交互,也知道不要把所有东西都搬到客户端。下一节回到服务器侧:在页面组件里取数据,让 Next.js 帮你把数据和页面一起准备好。

Footnotes

  1. Next.js Server and Client Components — https://nextjs.org/docs/app/getting-started/server-and-client-components

  2. React: Responding to Events — https://react.dev/learn/responding-to-events

  3. React: State: A Component's Memory — https://react.dev/learn/state-a-components-memory 2

练习

Level 1:判断是否需要 Client Component。
做法:给下面 5 个场景标 S 或 C。S 表示 Server Component 足够,C 表示需要 Client Component。

  1. 显示一篇静态介绍。
  2. 点击按钮展开说明。
  3. 渲染从服务器取来的文章列表。
  4. 输入关键词后实时过滤本页卡片。
  5. 显示一个不会变化的页脚。
提示 1

问自己:没有浏览器里的点击/输入,这块能不能先生成出来?

提示 2

useStateonClick 时,通常需要 Client Component。 Level 2:给作品卡片加收藏按钮。
做法:写一个 FavoriteButton Client Component,按钮在「收藏」和「已收藏」之间切换。把它放进作品卡片里。

看参考答案

1 S,2 C,3 S,4 C,5 S。

自评