React 类组件的生命周期有哪些?对应 Hooks 怎么写?
类组件生命周期
挂载阶段:
constructor → getDerivedStateFromProps → render → componentDidMount
更新阶段:
getDerivedStateFromProps → shouldComponentUpdate → render → getSnapshotBeforeUpdate → componentDidUpdate
卸载阶段:
componentWillUnmount生命周期详解
class MyComponent extends React.Component {
constructor(props) {
super(props)
// 初始化 state、绑定方法
}
static getDerivedStateFromProps(props, state) {
// 从 props 派生 state
return null
}
shouldComponentUpdate(nextProps, nextState) {
// 返回 false 阻止重渲染
return true
}
componentDidMount() {
// 挂载后:数据请求、订阅、DOM 操作
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// DOM 更新前读取信息(如滚动位置)
return null
}
componentDidUpdate(prevProps, prevState, snapshot) {
// 更新后:DOM 操作、网络请求
}
componentWillUnmount() {
// 卸载前:清除定时器、取消订阅
}
render() {
return <div />
}
}Hooks 对应关系
| 类组件生命周期 | Hooks 等价 |
|---|---|
| constructor | useState / useMemo 初始化 |
| componentDidMount | useEffect(() => {}, []) |
| componentDidUpdate | useEffect(() => {}, [dep]) |
| componentWillUnmount | useEffect(() => { return cleanup }, []) |
| shouldComponentUpdate | React.memo |
| getDerivedStateFromProps | 渲染期间直接计算 |
| getSnapshotBeforeUpdate | useLayoutEffect |
| forceUpdate | useReducer(强制触发) |
代码对照
// 类组件
class User extends React.Component {
componentDidMount() {
fetchUser(this.props.id)
}
componentDidUpdate(prevProps) {
if (prevProps.id !== this.props.id) {
fetchUser(this.props.id)
}
}
componentWillUnmount() {
this.controller.abort()
}
render() { return <div>{this.state.user}</div> }
}
// Hooks 等价
function User({ id }) {
const [user, setUser] = useState(null)
useEffect(() => {
const controller = new AbortController()
fetchUser(id, { signal: controller.signal })
.then(setUser)
return () => controller.abort() // cleanup = componentWillUnmount
}, [id]) // 依赖变化 = componentDidUpdate
return <div>{user}</div>
}废弃的生命周期(React 17+)
componentWillMountcomponentWillReceivePropscomponentWillUpdate
被废弃的原因是这些生命周期在 Fiber 异步渲染模式下可能被多次调用,导致不安全。