React 生命周期详解
React 组件的生命周期分为三个阶段:挂载(Mounting) 、更新(Updating)和卸载(Unmouting)。每个阶段包含不同的生命周期方法,用于控制组件的渲染、更新和销毁过程。
挂载阶段(Mounting)
挂载阶段是组件首次被创建并插入 DOM 的阶段,涉及以下方法:
constructor()
构造函数在组件初始化时调用,用于初始化 state 和绑定方法。若不初始化 state 或不绑定方法,可以省略 constructor。
javascript
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.handleClick = this.handleClick.bind(this);
}
}
static getDerivedStateFromProps()
该方法在组件实例化或接收到新 props 时调用,返回一个对象用于更新 state,或返回 null 表示不更新。
javascript
static getDerivedStateFromProps(props, state) {
if (props.value !== state.prevValue) {
return { prevValue: props.value };
}
return null;
}
render()
render 方法是类组件中唯一必须实现的方法,负责返回 JSX 结构。该方法必须是纯函数,不应修改 state 或与浏览器交互。
javascript
render() {
return <div>{this.state.count}</div>;
}
componentDidMount()
在组件挂载到 DOM 后立即调用,通常用于发起网络请求、订阅事件或操作 DOM。
javascript
componentDidMount() {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => this.setState({ data }));
}
更新阶段(Updating)
更新阶段发生在组件重新渲染时,可能由 props 或 state 的变化触发。
static getDerivedStateFromProps()
与挂载阶段相同,该方法在更新阶段也会被调用,用于根据 props 调整 state。
shouldComponentUpdate()
该方法决定组件是否需要重新渲染,默认返回 true。可通过比较新旧 props 或 state 优化性能。
javascript
shouldComponentUpdate(nextProps, nextState) {
return nextProps.value !== this.props.value;
}
render()
更新阶段再次调用 render 方法生成新的虚拟 DOM。
getSnapshotBeforeUpdate()
在 DOM 更新前捕获当前状态(如滚动位置),返回值将作为参数传递给 componentDidUpdate。
javascript
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevProps.list.length < this.props.list.length) {
return this.listRef.scrollHeight;
}
return null;
}
componentDidUpdate()
在组件更新后调用,适合执行 DOM 操作或网络请求。
javascript
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
this.listRef.scrollTop += this.listRef.scrollHeight - snapshot;
}
}
卸载阶段(Unmounting)
componentWillUnmount()
在组件卸载前调用,用于清理定时器、取消网络请求或移除事件监听。
javascript
componentWillUnmount() {
clearInterval(this.timerID);
this.subscription.unsubscribe();
}
错误处理
static getDerivedStateFromError()
在子组件抛出错误时调用,返回一个对象用于更新 state 以显示错误 UI。
javascript
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch()
用于记录错误信息,适合上报错误日志。
javascript
componentDidCatch(error, info) {
logErrorToService(error, info);
}
生命周期流程图
-
挂载阶段
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
-
更新阶段
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
-
卸载阶段
- componentWillUnmount
注意事项
- 避免副作用 :
render和getDerivedStateFromProps应是纯函数,避免直接修改 state 或执行异步操作。 - 性能优化 :合理使用
shouldComponentUpdate或React.memo减少不必要的渲染。 - 错误边界 :使用
getDerivedStateFromError和componentDidCatch防止组件树崩溃。
通过合理利用生命周期方法,可以更高效地管理组件状态、优化渲染性能并处理异常情况。