标准答案
- constructor 和 state 初始化通常对应函数组件里的 useState 初始值或 useReducer 初始值。
- componentDidMount 常见逻辑可以用 useEffect 空依赖数组表达。
- componentDidUpdate 可以用带依赖数组的 useEffect 表达,但要注意首次执行和依赖变化。
- componentWillUnmount 的清理逻辑对应 useEffect 返回的 cleanup 函数。
- 需要在浏览器绘制前读取布局并同步更新时,类组件相关逻辑更接近 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 里清理订阅、事件监听和定时器。