标准答案

  1. constructor 和 state 初始化通常对应函数组件里的 useState 初始值或 useReducer 初始值。
  2. componentDidMount 常见逻辑可以用 useEffect 空依赖数组表达。
  3. componentDidUpdate 可以用带依赖数组的 useEffect 表达,但要注意首次执行和依赖变化。
  4. componentWillUnmount 的清理逻辑对应 useEffect 返回的 cleanup 函数。
  5. 需要在浏览器绘制前读取布局并同步更新时,类组件相关逻辑更接近 useLayoutEffect。

题目解析

生命周期到 Hooks 不是一一替换 API 名称,而是把副作用按依赖拆分。

类组件里 mount/update/unmount 经常分散在不同生命周期中;Hooks 更鼓励把同一个副作用的创建和清理写在同一个 useEffect 里。

迁移时不要把所有逻辑都塞进一个 useEffect,应该按数据请求、订阅、DOM 测量等职责拆开。

代码示例

下面展示订阅逻辑在函数组件里如何把创建和清理放在一起。

TSX
function ChatRoom({ roomId }: { roomId: string }) {
  useEffect(() => {
    const connection = connectRoom(roomId)
    connection.open()

    return () => {
      connection.close()
    }
  }, [roomId])

  return <div>当前房间:{roomId}</div>
}

常见误区

  • 机械地把 componentDidMount 翻译成 useEffect 空依赖,忽略它读取的 props 和 state。
  • 把多个无关副作用放进一个 useEffect,依赖数组变得难以维护。
  • 忘记在 cleanup 里清理订阅、事件监听和定时器。

作者信息