生命周期
生命周期更改点
react16.4后被替换生命周期
在React16.3之前,由于开发者时常在componentWillMount中进行异步请求,而该方法会被多次调用,导致性能开销过大,官方将三类生命周期方法已被标记为不推荐使用(UNSAFE):
UNSAFE_componentWillMount
UNSAFE_componentWillReceiveProps
UNSAFE_componentWillUpdate
截至最新版本,React并没有完全废除这些UNSAFE的方法,但强烈建议开发者避免使用它们,并使用新的生命周期方法来替代,这样做的目的是为了更好地支持React未来的异步渲染特性。
- componentWillMount() : 在组件挂载之前调用,通常不推荐使用。
- componentWillReceiveProps(nextProps) : 当组件接收到新的props时调用,已被
getDerivedStateFromProps替代。 - componentWillUpdate(nextProps, nextState) : 在组件更新之前调用,已被
getSnapshotBeforeUpdate替代。
react16.3以前的生命周期
-
react16.3以前的生命周期:
主要分为 初始化阶段、更新阶段、卸载组件1.初始化阶段 constructor->componentWillMount->render->componentDidMount 2.更新阶段 componentWillReceiveProps->shouldComponentUpdate->componentWillUpdate-> render->componentDidUpdate 3.卸载组件 componentWillUnmount
16.4及以后的生命周期
-
react16.4及以后三个阶段主要有以下改变
1.创建阶段 constructor---->getDerivedStateFromProps---->render---->componentDidMount 2.更新阶段 getDerivedStateFromProps---->sholdComponentUpdate--->render---->getSnapshotBeforeUpdate --->componentDidupdate 3.阶段 componentWillUnmount
生命周期阶段的作用
- 挂载阶段 (Mounting)
在这个阶段,组件被创建并插入到DOM中。生命周期方法的调用顺序如下:
- constructor() : 初始化组件的状态和绑定事件处理方法。此方法在组件挂载之前调用。
- getDerivedStateFromProps(nextProps, prevState) : 在每次渲染之前调用,用于根据新的props更新state。它是一个静态方法,不能访问
this。 - render() : 渲染组件的UI。每次组件更新都会调用此方法。
- componentDidMount() : 组件挂载完成后调用,适合进行DOM操作和网络请求。
- 更新阶段 (Updating)
当组件的props或state发生变化时,会触发更新阶段。生命周期方法的调用顺序如下:
- getDerivedStateFromProps(nextProps, prevState) : 与挂载阶段相同,在更新时也会调用。
- shouldComponentUpdate(nextProps, nextState) : 决定组件是否需要重新渲染,返回
true或false。 - render() : 再次渲染组件的UI。
- getSnapshotBeforeUpdate(prevProps, prevState) : 在最近一次渲染输出之前调用,可以捕获一些信息(如滚动位置)。
- componentDidUpdate(prevProps, prevState, snapshot) : 组件更新后调用,适合进行DOM操作或网络请求。
- 卸载阶段 (Unmounting)
当组件从DOM中移除时,会调用以下方法:
- componentWillUnmount() : 组件卸载之前调用,适合清理定时器或取消网络请求等。
import React from "react";
class LifecycleComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
console.log("Constructor");
}
static getDerivedStateFromProps(props, state) {
console.log("getDerivedStateFromProps");
return null;
}
componentDidMount() {
console.log("componentDidMount");
}
shouldComponentUpdate(nextProps, nextState) {
console.log("shouldComponentUpdate");
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log("getSnapshotBeforeUpdate");
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("componentDidUpdate");
}
componentWillUnmount() {
console.log("componentWillUnmount");
}
handleClick = () => {
this.setState((prevState) => ({ count: prevState.count + 1 }));
};
render() {
console.log("render");
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.handleClick}>Increment</button>
</div>
);
}
}
export default LifecycleComponent;
函数组件生命周期替代方案
useEffect((params) => {
return params;
}, dep);
- useEffect拥有两个参数
1.1 第一个参数callback,会返回一个清理函数,用于清理副作用。
1.2 第二参数为可选依赖项dep,用于控制副作用函数的执行时机 - useEffect 执行为异步执行,每次该函数执行后,会将useEffect的第一参数callback()放入任务队列中,等到主线程任务完成,包括DOM 更新,js 执行完成,视图绘制后,在进行callback()的执行。
//当useEffect依赖项为空数组时,
useEffect(() => {
// 请求数据,事件监听,订阅和取消订阅,操纵dom,定时器等操作
console.log("组件挂载完成:componentDidMount");
return function componentWillUnmount() {
/* 解除事件监听器 ,清除 */
console.log("组件销毁:componentWillUnmount");
};
}, []);
//当useEffect依赖项为某个变量时,此时可监听,该变量的变化
useEffect(() => {
console.log("props变化:componentWillReceiveProps");
}, [props]);
// 无依赖项时,可模拟组件更新
useEffect(() => {
console.log(" 组件更新完成:componentDidUpdate ");
});
生命周期注意点:
- 避免在constructor中进行副作用操作,constructor主要用于初始化state和绑定方法,不应该在这里进行网络请求等副作用操作。
- 不要在componentWillMount中进行异步操作,componentWillMount在React 16.3后被废弃,且可能会多次调用,不适合进行异步操作。
- 不要在render中修改state,render应该是一个纯函数,不应该有副作用。
- 在componentDidUpdate中注意条件判断,为避免无限循环,在这里更新state时必须加条件判断。
- 在componentWillUnmount中清理资源,取消网络请求、清除定时器等清理工作应在此进行。
- 使用错误边界(Error Boundaries)处理错误,通过componentDidCatch或static getDerivedStateFromError来捕获和处理错误。