- 原文地址 – 全栈小册:https://skillgroup.cn/framework/react/life-cycle.html
React 生命周期流程图
React 生命周期线上地址
React.Component 构造函数
1. 目标
构造函数在 React 组件的生命周期中十分晚期被调用,它产生在组件实例被创立并插入到 DOM 之前。这使得它成为初始化组件的本地状态和绑定事件处理函数的现实地位。
2. 应用
如果您的组件不须要初始化状态或绑定事件处理函数,那么您不须要显式地定义一个构造函数。然而,如果您的确这样做了,那么在构造函数的第一行调用 super(props)
是必要的。
3. 为什么要调用 super(props)
?
在 JavaScript 类中,子类的构造函数必须在应用 this
之前调用 super
。在 React 组件中,super
援用的是 React.Component
的构造函数。调用 super(props)
确保您能够在构造函数中应用this.props
。
4. 初始化状态
构造函数是为 this.state
设置初始值的中央。这是通过间接为 this.state
调配一个对象来实现的。例如:
this.state = {counter: 0};
请留神,您不应该在构造函数中调用setState()
。
5. 绑定事件处理函数
为了确保事件处理函数中的 this
援用的是组件实例,您须要在构造函数中绑定它。例如:
this.handleClick = this.handleClick.bind(this);
6. 防止的做法
- 不要在构造函数中调用
setState()
:这是因为this.state
能够间接在构造函数中进行初始化。 - 防止引入副作用或订阅 :构造函数不是执行网络申请、设置订阅或手动更改 DOM 的中央。这些都应该在
componentDidMount()
或其余生命周期办法中进行。 - 防止将 props 间接复制到 state:这是因为当 props 更改时,state 不会自动更新,可能导致组件的渲染状态与 props 不同步。
7. 示例代码
class MyComponent extends React.Component {constructor(props) {super(props);
this.state = {counter: 0};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {// 事件处理逻辑}
// ... 其余办法和渲染逻辑
}
8. 不应用构造函数的代替办法
constructor
在 React 组件中是能够省略的。然而,是否省略取决于您的组件须要执行哪些初始化操作。以下是一些状况阐明:
不须要初始化状态,也不须要绑定办法
如果您的组件不须要初始化本地状态,并且您也不须要绑定任何办法到组件实例,那么您能够齐全省略constructor
。
应用类属性
在古代的 React 版本中,您能够应用类属性来初始化状态,而不须要显式的constructor
。例如:
class MyComponent extends React.Component {state = { counter: 0};
// ... 其余代码
}
应用箭头函数主动绑定办法
如果您应用箭头函数定义方法,那么这些办法会主动绑定到以后实例,因而不须要在 constructor
中进行绑定。例如:
class MyComponent extends React.Component {handleClick = () => {// 事件处理逻辑};
// ... 其余代码
}
综上所述,如果您应用类属性和箭头函数,那么在许多状况下,您都能够省略constructor
。然而,如果您须要执行更简单的初始化逻辑,或者须要在创立组件实例时执行某些操作,那么依然须要constructor
。
getDerivedStateFromProps
在 React 的世界里,组件的属性(props)和状态(state)是外围概念。有时,咱们须要依据属性的变动来更新状态。这就是 getDerivedStateFromProps
办法的舞台。
什么是getDerivedStateFromProps
?
getDerivedStateFromProps
是 React 组件的一个动态生命周期办法。它容许咱们在组件接管新的属性时更新状态。这个办法在组件的挂载和更新阶段都会被调用。
执行机会
1. 挂载阶段(Mounting)
当组件实例被创立并插入到 DOM 中时,getDerivedStateFromProps
会在 render
办法之前被调用。这容许您依据组件的初始属性来设置组件的初始状态。
2. 更新阶段(Updating)
当组件接管到新的属性或状态更改时,getDerivedStateFromProps
也会被调用。具体来说,它会在以下状况下被调用:
- 当组件接管到新的属性时(即父组件从新渲染)。
- 当您调用
setState
办法更新组件的状态时。 - 当您调用
forceUpdate
办法强制从新渲染组件时。
在这些状况下,getDerivedStateFromProps
都会在 render
办法之前被调用,容许您依据新的属性或状态来更新组件的状态。
参数解释
- nextProps:组件行将接管的新属性。
- prevState:组件以后的状态。
返回值
- 返回一个对象来更新状态。
- 如果不须要更新状态,则返回 null。
利用场景
- 属性派生状态 :当组件的外部状态须要从属性派生时。
假如您有一个主题组件,它的色彩能够通过属性来管制,但也能够由用户在组件外部更改。
class ThemeComponent extends React.Component {state = { color: this.props.color};
static getDerivedStateFromProps(nextProps, prevState) {if (nextProps.color !== prevState.color) {return { color: nextProps.color};
}
return null;
}
render() {return <div style={{ backgroundColor: this.state.color}}> 主题色彩 </div>;
}
}
- 条件渲染 :依据属性管制组件的渲染。
假如一个权限管制组件可能会依据传入的权限级别显示或暗藏某些性能。
class PermissionComponent extends React.Component {state = { isAdmin: this.props.isAdmin};
static getDerivedStateFromProps(nextProps, prevState) {if (nextProps.isAdmin !== prevState.isAdmin) {return { isAdmin: nextProps.isAdmin};
}
return null;
}
render() {return this.state.isAdmin ? <AdminFeatures /> : <UserFeatures />;}
}
注意事项
- getDerivedStateFromProps 是一个静态方法,因而它不能拜访组件实例的 this。这意味着您不能在此办法中调用组件的实例办法或拜访组件的实例属性。
- 因为 getDerivedStateFromProps 在多个阶段都可能被调用,因而您可能须要增加额定的逻辑来确定何时应该更新状态。
- getDerivedStateFromProps 应该是一个纯函数,不要在其中执行有副作用的操作,如网络申请或订阅事件。
shouldComponentUpdate
1. 根本用法
shouldComponentUpdate
是一个可选的生命周期办法,用于在接管新的 props 或 state 时确定组件是否应该从新渲染。它返回一个布尔值,通知 React 是否应持续更新过程。
shouldComponentUpdate(nextProps, nextState) {
// 逻辑判断
return true 或 false;
}
2. 性能优化
a. 防止不必要的渲染
如果您的组件常常接管雷同的 props 或 state,但不须要每次都从新渲染,那么 shouldComponentUpdate
就派上用场了。
shouldComponentUpdate(nextProps, nextState) {return nextProps.value !== this.props.value;}
b. 自定义比拟逻辑
您能够依据须要编写自定义的比拟逻辑,只有在满足特定条件时才从新渲染。
3. 与 PureComponent 的关系
React.PureComponent
通过浅比拟 props 和 state 来主动实现 shouldComponentUpdate
。如果您的组件继承自 PureComponent
,则不须要手动实现此办法。
4. 执行机会
1. 接管新的 Props 或 State
当组件接管到新的 props 或 state 时,shouldComponentUpdate
将被调用。这是一个决策点,让您能够判断是否真的须要从新渲染组件。
2. 父组件从新渲染
当父组件从新渲染时,子组件的 shouldComponentUpdate
也会被调用。这样,您能够管制子组件是否随父组件一起从新渲染。
3. 应用 forceUpdate
如果您调用了组件的 forceUpdate
办法,shouldComponentUpdate
将被跳过,组件将强制从新渲染。
4. 初始化渲染
值得注意的是,shouldComponentUpdate
不会在组件的初始化渲染阶段被调用。它仅在组件的更新阶段起作用。
5. 注意事项和最佳实际
a. 防止副作用
shouldComponentUpdate
只利用于渲染决策,不应执行任何副作用,如网络申请或批改全局变量。
b. 防止深度比拟
深度比拟可能会耗费大量性能,反而升高利用的响应速度。
c. 不要在此办法中调用 setState
这会导致组件从新渲染,从而引发有限循环。
getSnapshotBeforeUpdate
1. 什么是 getSnapshotBeforeUpdate
?
getSnapshotBeforeUpdate
是 React 的一个生命周期办法,用于在 DOM 更新之前捕捉一些信息。这个办法在最新的渲染输入被提交到 DOM 之前被调用,容许您在更新产生之前捕捉一些对于 DOM 的信息。
2. 办法签名
getSnapshotBeforeUpdate(prevProps, prevState);
prevProps
: 更新前的属性。prevState
: 更新前的状态。
3. 返回值
这个办法应返回一个值,该值将作为 componentDidUpdate
的第三个参数。如果您不须要捕捉任何信息,能够返回 null
。
4. 应用场景
a. 捕捉滚动地位
如果您的组件波及到滚动,并且在更新后须要放弃滚动地位,能够应用以下代码:
getSnapshotBeforeUpdate() {return this.containerElement.scrollTop;}
componentDidUpdate(prevProps, prevState, snapshot) {this.containerElement.scrollTop = snapshot;}
b. 捕捉表单状态
如果您的组件蕴含表单,并且您想在更新之前捕捉表单的状态,能够这样做:
getSnapshotBeforeUpdate() {return this.formElement.values;}
componentDidUpdate(prevProps, prevState, snapshot) {// 应用捕捉的表单状态}
c. 比拟属性和状态
您还能够应用这个办法来比拟前后属性和状态的变动,从而执行一些特定的逻辑。
5. 注意事项
getSnapshotBeforeUpdate
必须与componentDidUpdate
配合应用。- 不要在这个办法中触发状态更新,否则会导致有限循环。
componentDidMount
在 React 18 中,componentDidMount
依然是一个重要的生命周期办法,但随着 React Hooks 的风行,许多开发人员可能会转向应用 useEffect
钩子来代替。不过,对于那些仍在应用类组件的我的项目,componentDidMount
依然是一个弱小的工具。
1. 数据获取
componentDidMount
是一个现实的中央来执行异步操作,例如从 API 获取数据。这样做能够确保组件曾经挂载到 DOM 中,因而您能够平安地更新状态。
componentDidMount() {fetch('/api/data')
.then(response => response.json())
.then(data => this.setState({ data}));
}
2. 增加事件监听器
如果您须要在组件挂载后增加事件监听器,componentDidMount
是一个完满的中央。
componentDidMount() {window.addEventListener('resize', this.handleResize);
}
3. 操作 DOM
如果您须要间接操作 DOM,componentDidMount
能够确保 DOM 曾经筹备好。
componentDidMount() {this.myInput.focus();
}
4. 执行机会
componentDidMount
是一个生命周期办法,它会在组件第一次渲染到 DOM 之后立刻调用。这意味着它是在组件的第一次渲染实现后执行的,但在任何子组件的 componentDidMount
之前执行。
上面是执行机会的具体解释:
- 组件挂载实现:当组件被插入到 DOM 中后,
componentDidMount
将被调用。此时,您能够平安地执行波及 DOM 的操作。 - 仅执行一次:与其余生命周期办法不同,
componentDidMount
只在组件挂载后执行一次。如果您须要在组件更新后执行某些操作,您可能须要应用componentDidUpdate
。 - 在子组件的
componentDidMount
之前执行:如果有子组件,父组件的componentDidMount
将在任何子组件的componentDidMount
之前执行。 - 在
render
办法之后执行:componentDidMount
是在render
办法之后执行的,所以在componentDidMount
中调用setState
将触发额定的渲染,但这不会让用户看到中间状态。
哎呀,你齐全对了!我居然忘了提到 componentDidUpdate
的执行机会,这可是理解它的要害局部。让我补充一下:
componentDidUpdate 执行机会
1. 组件更新后
componentDidUpdate
的名字曾经暗示了它的执行机会:组件更新后。然而,什么会导致组件更新呢?
- 属性变动:当组件接管到新的属性时,它会触发更新。
- 状态变动:当组件的状态扭转时,它也会触发更新。
- 父组件从新渲染:即便属性和状态没有扭转,父组件的从新渲染也会导致子组件更新。
2. 不会在初始渲染时执行
当组件首次挂载时,componentDidUpdate
是不会被调用的。如果你须要在首次渲染后执行某些操作,能够应用 componentDidMount
办法。
3. 在 render
办法之后
componentDidUpdate
是在 render
办法之后执行的,所以你能够确信此时 DOM 曾经更新。这使得 componentDidUpdate
成为执行与 DOM 相干操作的现实机会。
4. 在 getSnapshotBeforeUpdate
之后
如果你应用了 getSnapshotBeforeUpdate
办法,那么 componentDidUpdate
会在它之后执行。这样你能够在 getSnapshotBeforeUpdate
中捕捉一些信息,并在 componentDidUpdate
中应用。
5. 根底用法
componentDidUpdate
的根底用法非常简单。它接管三个参数:
componentDidUpdate(prevProps, prevState, snapshot) {// ...}
- prevProps:前一个属性对象。
- prevState:前一个状态对象。
- snapshot:从
getSnapshotBeforeUpdate
办法返回的值。
componentWillUnmount
1. 什么是 componentWillUnmount
?
在 React 中,当一个组件不再须要时,componentWillUnmount
办法会被调用。这是一个清理组件相干资源的好时机。
2. componentWillUnmount
的用法
清理定时器
如果组件中设置了定时器,当组件卸载时,定时器应该被革除,以防止不必要的谬误和资源节约。
componentWillUnmount() {clearInterval(this.timerID);
}
勾销网络申请
如果组件中发动了网络申请,当组件卸载时,应该勾销未实现的申请,以防止不必要的正告和潜在的谬误。
componentWillUnmount() {this.source.cancel('组件卸载,勾销申请');
}
移除事件监听器
如果组件中增加了事件监听器,当组件卸载时,应该移除这些监听器,以防止内存透露。
componentWillUnmount() {window.removeEventListener('resize', this.handleResize);
}