# 类组件生命周期方法
# 各个生命周期方法的作用
# constructor
可以在 constructor 方法中,做一些初始化的工作,比如初始化状态、绑定方法等等。
# getDerivedStateFromProps
官方介绍: static getDerivedStateFromProps(props, state) (opens new window)
这个方法会在 render 函数执行之前调用,且在初始化挂载和后续更新时都会被调用,这个方法内部是访问不到 this 的。
import React, { Component } from 'react';
export default class Demo extends Component {
static getDerivedStateFromProps() {}
render() {
return 1;
}
}
上面这样使用会报错:

使用的时候一定要初始化一个状态,并且返回一个对象,它返回值将作为新的 state 合并到 state 中。
import React, { Component } from 'react';
export default class Demo extends Component {
state = {
age: 18
};
static getDerivedStateFromProps(nextProps, prevState) {
console.log(nextProps, prevState);
/*
第一次渲染时的输出:
{} {age: 18}
age更新后的输出:
{} {age: 19, name: "f"}
*/
return { name: 'f' };
}
shouldComponentUpdate(nextProps, nextState) {
console.log(nextState);
return true;
}
componentDidMount = () => {
setTimeout(() => {
this.setState({
age: 19
});
}, 5000);
};
render() {
return (
<div>
<span>{JSON.stringify(this.state)}</span>
</div>
);
}
}
getDerivedStateFromProps 作用:
- 替代 componentWillMount 和 componentWillReceiveProps;
- 根据最新的 props 计算 state;
# UNSAFE_componentWillMount
这个方法会在 render 函数执行之前被调用,这个方法未来可能会被废弃,所以不建议在里面写什么代码。
# UNSAFE_componentWillReceiveProps
一般是在子组件的 props 发生改变后会触发 UNSAFE_componentWillReceiveProps ,但是像下面这个代码,子组件中的 props 并没有发生改变,浏览器控制台还是打印了 'componentWillReceiveProps',这是为什么呢?
import React, { Component } from 'react';
class Child extends Component {
componentWillReceiveProps = (nextProps) => {
console.log('componentWillReceiveProps');
};
render() {
return 'child';
}
}
export default class Deom extends Component {
state = {
age: 16
};
componentDidMount = () => {
setTimeout(() => {
this.setState({
age: 17
});
}, 2000);
};
render() {
return <Child />;
}
}
这是因为当父组件中的 state 发生变化的时候,会触发父组件的 render 函数执行,会调用 React.createElement 方法,重新创建 props,所以子组件中的 componentWillReceiveProps 会重新执行。
# getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps,preState) 方法主要用来获取一次更新前的信息,并这个信息传递给 componentDidUpdate 方法的第三个参数。
getSnapshotBeforeUpdate(prevProps,preState) 需要和 componentDidUpdate 配合使用。
import React, { useEffect, useState, Component } from 'react';
export default class Deom extends Component {
getSnapshotBeforeUpdate() {}
render() {
return 1;
}
}
上面这样写会报警告:

# 函数组件中的生命周期替代方案
在函数组件中我们可以通过 useEffect (opens new window) 或者 useLayoutEffect (opens new window) 来模拟类组件中的生命周期。
useEffect 的函数会在浏览器完成布局与绘制之后,在一个延迟事件中被调用。
useLayoutEffect 它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。
# 代替 componentDidMount
React.useEffect(()=>{
/* 请求数据 , 事件监听 , 操纵dom */
},[]) /* 切记 dep = [] */
# 代替 componentWillUnmount
React.useEffect(()=>{
/* 请求数据 , 事件监听 , 操纵dom , 增加定时器,延时器 */
return function componentWillUnmount(){
/* 解除事件监听器 ,清除定时器,延时器 */
}
},[])/* 切记 dep = [] */
# 代替 componentWillReceiveProps
React.useEffect(()=>{
console.log('props变化:componentWillReceiveProps')
},[ props ])
# 代替 componentDidUpdate
React.useEffect(()=>{
console.log('组件更新完成:componentDidUpdate ')
}) /* 没有 dep 依赖项 */
useEffect 在初始化的时候会默认执行一次,但是 componentWillReceiveProps、componentDidUpdate 只有在依赖改变的时候才会执行。
# 问答
# 为什么componentWillMount会有执行多次的可能呢?
因为 render 过程会被优先级更高的打断。
# 当 props 不变的前提下, PureComponent 组件能否阻止 componentWillReceiveProps 执行?
componentWillReceiveProps 生命周期的执行,和纯组件没有关系,纯组件是在 componentWillReceiveProps 执行之后浅比较 props 是否发生变化。所以 PureComponent 下不会阻止该生命周期的执行。