R40第 1 / 1 课时未开始内容版本 1.0.0 · 核验于 2026-10-26

Hook 组合综合实践

Hook 组合综合实践 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。

学习目标

这一课把前面课程积累的 Hook 能力组合起来做一件真实的事:可搜索的命令面板。读完你应该能自己组合「受控输入 + 异步检索(带竞态保护)+ 键盘导航 + 清理」,并用快速输入、连按方向键的组合操作验证正确性。

问题场景

应用里常见的 Ctrl+K 面板:输入关键词,异步检索命令列表,↑↓ 选择,回车执行。拆开看每项能力都学过——受控输入、Effect 清理、请求竞态、自定义 Hook——难点在它们于同一组件里的组合:每秒十几次按键时,检索、选中、清理不能互相踩。

核心解释

组合的思路是「每个 Hook 只负责一件事,先做对,再组装」。检索部分先做成自定义 Hook,把竞态保护藏在里面:

function useCommandSearch(keyword) {
  const [items, setItems] = useState([]);
  useEffect(() => {
    let alive = true;                 // 竞态保护:只有最后一次输入的结果能落地
    const timer = setTimeout(() => {  // 防抖:停手 150ms 才检索
      searchCommands(keyword).then((r) => {
        if (alive) setItems(r);
      });
    }, 150);
    return () => { alive = false; clearTimeout(timer); };
  }, [keyword]);
  return items;
}

键盘导航是纯状态机:selectedIndex 加三个动作(上移 / 下移 / 确认),用函数式更新保证连按不丢:

const move = (delta) =>
  setSelectedIndex((i) =>
    items.length ? (i + delta + items.length) % items.length : 0
  );

组装时的三个顺序问题:items 变化后 selectedIndex 要夹回有效范围(Effect 里同步,否则列表从 10 条变 2 条后回车会执行错行);keydown 监听器在面板打开时挂、关闭时清(建立与清理成对);检索结果回落时,旧结果的选中位置不能直接套在新列表上。这三处正是「状态 + 清理 + 竞态」交界处最容易出的 bug。验证方式:快速输入乱按、狂按方向键后回车,执行的必须是「当前可见且选中」的那一条。

示例拆解

实验区命令面板内置 36 条命令,检索带 300ms 模拟延迟:

  • 输入关键词,停手 150ms 后发起检索;等待期间状态栏显示「检索中…」;
  • ↑ / ↓ 移动选中项,回车执行并记录,Esc 清空关键词;检索结果列表高亮当前选中行;
  • 状态栏显示「过期响应丢弃」计数:快速连续输入时,中间输入触发的检索在落地前就被清理函数作废;
  • 验证:快速输入 5 个字符,最终列表只反映最后一次输入;狂按方向键后回车,执行的是当前选中项。

动手任务

打开本课实验区:

  1. 把防抖从 150ms 调到 600ms,快速输入并观察「检索中…」次数明显减少——体会防抖(少发)与竞态保护(晚到作废)的分工。
  2. 去掉 alive 保护,快速输入几个字,找出「旧结果覆盖新输入」的复现步骤,再恢复。
  3. 加 Home / End 键:选中跳到第一 / 最后一项,确认越界保护仍然成立。

常见错误

  • 竞态保护写在落地之后:保护必须在「落地前」用闭包标记判断;结果已经 setState 了再判断毫无意义。
  • 导航索引不随列表收窄:列表从 10 条变 2 条,selectedIndex 还停在 7,回车执行错行;在 Effect 里同步夹取。
  • 监听器挂在 window 却不清理:面板关闭后按方向键还在移动选中项;打开时挂、关闭时清。
  • 把所有逻辑塞进一个 useEffect:输入、检索、导航互相纠缠,改一处动全身;先拆成独立 Hook,组合时只关心接口。

检查与复盘

自查清单:

  • 能列出面板的状态清单:keyword / items / selectedIndex / 执行记录,并说出各自归属
  • 快速输入 + 连按方向键 + 回车的组合测试通过
  • 每个自定义 Hook 能单独解释:输入、输出、清理行为

参考资料

动手实验
动手实验
预览
点击「运行」在隔离沙箱中预览
检查题共 1 题,提交后立即显示解析
答案由服务端判定;答错的题会自动进入复习计划。
Q1多选中等(多选,全部选对才算正确)

下列关于 Hooks 组合使用的说法,正确的有?(多选)

读完这一课了?

标记完成后,工作台会安排接下来的学习。

Command Palette

Search for a command to run...