生命周期到 useEffect 映射
约 524 字大约 2 分钟
布欧-Lewyon
2026-05-15
类组件中与生命周期相关的一切副作用,在 Hooks 中都由 useEffect(及其变体)统一接管。
生命周期映射表
| 类组件生命周期 | Hooks 等价写法 |
|---|---|
componentDidMount | useEffect(() => { ... }, []) |
componentDidUpdate(prevProps) | useEffect(() => { ... }, [prop]) |
componentWillUnmount | useEffect(() => { return () => { ... } }, []) |
shouldComponentUpdate | React.memo + useMemo |
componentDidMount → useEffect(fn, [])
// 类组件
class UserList extends React.Component {
state = { users: [], loading: true }
componentDidMount() {
fetch('/api/users')
.then(r => r.json())
.then(users => this.setState({ users, loading: false }))
}
render() { /* ... */ }
}// Hooks 版本
function UserList() {
const [users, setUsers] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
fetch('/api/users')
.then(r => r.json())
.then(data => { setUsers(data); setLoading(false) })
}, []) // 空依赖 → componentDidMount
// ...
}componentDidUpdate → useEffect(fn, [deps])
// 类组件
componentDidUpdate(prevProps) {
if (prevProps.userId !== this.props.userId) {
this.fetchUser(this.props.userId)
}
}// Hooks 版本
useEffect(() => {
fetchUser(userId)
}, [userId]) // userId 变化时执行获取前一个值
// 类组件可以通过 prevProps 拿到前一个值
// Hooks 需要用 useRef 模拟
function usePrevious<T>(value: T): T | undefined {
const ref = useRef<T>()
useEffect(() => { ref.current = value }, [value])
return ref.current
}
function Profile({ userId }: { userId: number }) {
const prevUserId = usePrevious(userId)
useEffect(() => {
if (prevUserId !== userId) {
console.log(`从 ${prevUserId} 切换到 ${userId}`)
fetchUser(userId)
}
}, [userId])
}componentWillUnmount → return cleanup
// 类组件
class Timer extends React.Component {
intervalId: number
componentDidMount() {
this.intervalId = setInterval(this.tick, 1000)
}
componentWillUnmount() {
clearInterval(this.intervalId)
}
}// Hooks 版本
function Timer() {
const [count, setCount] = useState(0)
useEffect(() => {
const id = setInterval(() => setCount(c => c + 1), 1000)
return () => clearInterval(id) // componentWillUnmount
}, [])
return <div>{count}</div>
}getDerivedStateFromProps → 直接渲染
// 类组件 — 反模式
static getDerivedStateFromProps(props, state) {
if (props.id !== state.prevId) {
return { prevId: props.id, filtered: data.filter(...) }
}
return null
}// Hooks 版本 — 直接计算
function List({ items, filter }: { items: Item[]; filter: string }) {
// ✅ 直接渲染时计算,不需要额外同步
const filtered = useMemo(() =>
items.filter(i => i.name.includes(filter)),
[items, filter]
)
return <>{filtered.map(...)}</>
}迁移清单
componentDidMount → useEffect(fn, [])
componentDidUpdate → useEffect(fn, [deps])
componentWillUnmount → useEffect(() => fn, []) cleanup
shouldComponentUpdate → React.memo + useMemo
getDerivedStateFromProps → 直接渲染计算 + useMemo
getSnapshotBeforeUpdate → useInsertionEffect (不常见)
constructor → useState 初始值 / useRef小结
[]空依赖 = componentDidMount,[deps]= componentDidUpdate。- 清除函数 return = componentWillUnmount。
usePrevious自定义 Hook 模拟 prevProps。getDerivedStateFromProps在 Hooks 中直接用 useMemo 替代。- React.memo 替代 shouldComponentUpdate。
上一节:无(迁移专题第一篇) 下一节:setState 到 useState/useReducer
