React 常用 Hooks

0 阅读3分钟

React 常用 Hooks

前置:React 列表与表单
目标:掌握 useEffect / useMemo,并会抽自定义 Hook。

引言

useState 管组件里的数据;一碰到「改标题、开定时器、订消息」,就要 useEffect。贵计算用 useMemo;多处重复的逻辑,抽成 自定义 Hook。

本篇 demo:搜索词同步到 document.title、每秒 ticks++、useMemo 算 doubled。

动手

完整代码:react2/05-hooks/demo

cd react2/05-hooks/demo
npm install && npm run dev

输入框打字看浏览器标签页标题变化;下面计时会每秒跳一次。


1. useState:组件内状态

const [query, setQuery] = useState('')
const [ticks, setTicks] = useState(0)
  • 第一个值是当前 state,第二个是更新函数。
  • 输入框受控:value={query},onChange 里 setQuery。
  • 计时不要写 setTicks(ticks + 1) 连点踩旧值;用函数式:setTicks((t) => t + 1)。

2. useEffect:同步到外部系统

React 渲染只负责 UI。改 document.title、setInterval、订阅,都属于「外部系统」,放进 useEffect。

定时器(挂载一次)

useEffect(() => {
  const id = window.setInterval(() => setTicks((t) => t + 1), 1000)
  return () => window.clearInterval(id) // 卸载时清理
}, [])
  • 依赖数组 []:只在挂载时跑,卸载时执行清理。
  • 忘了 clearInterval → 切页后定时器还在跑,可能报错或泄漏。

依赖变了再跑

自定义 Hook 里按 title 更新文档标题:

useEffect(() => {
  const prev = document.title
  document.title = title
  return () => {
    document.title = prev // 还原,避免脏标题残留
  }
}, [title])

title 变 → 先跑上一次的 cleanup,再跑新的 effect。

怎么选依赖

依赖含义
[]只挂载 / 卸载各一次
[a, b]a 或 b 变就重跑
省略每次渲染后都跑(几乎总是错的,别省略)

3. useMemo:缓存计算结果

const doubled = useMemo(() => ticks * 2, [ticks])

只有 ticks 变才重算。本 demo 里 ticks * 2 很便宜,是为了看清写法。

什么时候值得用:

  • 计算明显贵(大列表过滤、复杂派生数据)
  • 要把「引用稳定」的值传给下游(配合 memo / 依赖数组)

什么时候别用: 简单加减、拼字符串——多包一层反而难读,优化收益为零。


4. 自定义 Hook:复用带状态的逻辑

约定:名字以 use 开头,内部可以调其它 Hooks。

function useDocumentTitle(title: string) {
  useEffect(() => {
    const prev = document.title
    document.title = title
    return () => {
      document.title = prev
    }
  }, [title])
}

// 组件里一行搞定
useDocumentTitle(query ? `搜索:${query}` : 'Hooks 示例')

好处:标题逻辑和 UI 解耦;别的页面也能 useDocumentTitle('设置')。


对照表

Hook / 模式干什么demo 里的例子
useState组件状态query、ticks
useEffect同步外部系统 + 清理定时器、document.title
useMemo按依赖缓存计算结果doubled = ticks * 2
自定义 Hook打包可复用逻辑useDocumentTitle

常见坑

做法问题
effect 里改 state 却漏依赖闭包拿到旧值;或 eslint 警告被忽略后行为诡异
订阅 / 定时器不 cleanup内存泄漏、卸载后仍 setState
到处 useMemo / useCallback代码变吵,性能没变好
自定义 Hook 不以 use 开头没法静态检查 Hooks 规则

demo 在练什么

App.tsx 三件事叠在一起:

  1. 搜索框 → useDocumentTitle 改标签页标题
  2. useEffect + setInterval → ticks 每秒 +1,卸载清理
  3. useMemo → 展示 doubled

自己改一改:把 useMemo 换成「输入长度 > 3 才显示 doubled」,或给 useDocumentTitle 加前缀 [App]。


运行截图

Hooks 示例页

下一篇

React 路由:React Router