React 类组件的生命周期有哪些?PureComponent 与 Hooks 怎样对应?
先理解原理和示例,再练习完整口述与追问。
回答要点
挂载:constructor → getDerivedStateFromProps → render → componentDidMount;更新:getDerivedStateFromProps → shouldComponentUpdate → render → getSnapshotBeforeUpdate → componentDidUpdate;卸载:componentWillUnmount;错误:getDerivedStateFromError 与 componentDidCatch。PureComponent 对 props 和 state 做浅比较,类似函数组件的 memo。Hooks 中 useEffect 覆盖挂载、更新和卸载副作用,错误边界仍需类组件。
原理拆解
render 阶段(render、getDerivedStateFromProps、shouldComponentUpdate)必须是纯函数,在并发渲染中可能执行多次或被丢弃;提交阶段(componentDidMount、componentDidUpdate、componentWillUnmount)只执行一次,适合副作用。componentWillMount、componentWillReceiveProps、componentWillUpdate 因为位于可能重复执行的渲染阶段而被标为 UNSAFE。
getSnapshotBeforeUpdate 在 DOM 更新前读取信息(如滚动位置),返回值传给 componentDidUpdate;函数组件中近似用 useLayoutEffect 配合 ref 实现。useEffect(fn, []) 不等于 componentDidMount:它在浏览器绘制之后异步执行,而且 StrictMode 开发环境会挂载、卸载、再挂载一次,以检查清理是否正确。
示例与推演
class ErrorBoundary extends React.Component {
state = { error: null }
static getDerivedStateFromError(error) { return { error } }
componentDidCatch(error, info) { report(error, info.componentStack) }
render() { return this.state.error ? this.props.fallback : this.props.children }
}
错误边界只能捕获后代组件渲染和生命周期中的错误,不能捕获事件处理函数和异步代码中的错误,那些需要 try...catch。
易错点
shouldComponentUpdate 返回 false 会跳过子树更新,但 Context 变化仍会让消费它的子组件更新;PureComponent 遇到每次新建的对象或函数 props 会失效。
参考回答可直接练习口述
类组件挂载时依次是 constructor、getDerivedStateFromProps、render、componentDidMount;更新时多了 shouldComponentUpdate 和 getSnapshotBeforeUpdate,最后 componentDidUpdate;卸载是 componentWillUnmount,错误边界用 getDerivedStateFromError 和 componentDidCatch。render 阶段要保持纯净,副作用放在提交阶段。PureComponent 做浅比较,对应 memo;函数组件用 useEffect 处理副作用及清理,但错误边界目前仍要用类组件。