GX博客

分享个人 Full-Stack JavaScript 项目开发经验

React类组件生命周期一览

了解 React 类组件生命周期的使用方式,对组件构建、性能优化和避免副作用十分重要。下面依据 16 版本的 React 和紧跟其 17 版本,整理以下生命周期说明。


import PropTypes from "prop-types";

class Example extends React.Component {

    constructor(props) {

        // 必须在使用 this 关键字之前使用,传入参数 props 调用父类的构造函数。
        super(props);

        // 可以在这里基于 props 来初始化 state,但 state 不会随 props 更新而更新。
        this.state = {
            color: props.initialText
        };
    }

    handleChange = () => {

        // 该语法为属性初始化器语法的箭头函数,this 被绑定到组件类

        this.setState((prevState, props) => stateChange, [callback]);

        // 注意:setState() 是异步的,其可能是批处理或推迟更新。
        // 所以基于渲染之后执行的操作,应该在参数二的回调函数中或者 componentDidUpdate 生命周期函数中完成。
        // stateChange 将会浅合并到新状态中,它也可以直接以对象形式给出。
    }

    handleModelChange() {

        // 当组件依赖的外部数据发生改变,可以使用 forceUpdate()。
        // 它会忽略该组件的 shouldComponentUpdate(),导致 render() 方法被调用。
        // 它也将会触发每个子组件的生命周期方法。

        this.forceUpdate();

        // 通常情况,应该尽量避免使用它,组件仅从 this.props 和 this.state 中读取数据
    }

    static getDerivedStateFromProps(nextProps, prevState) {

        // 组件实例化后,接受新 props 时会调用。

        // 该方法意思是从新 props 中获得衍生 state。
        // 返回 null 表明不需要更新任何状态。
        // 返回对象将用于更新新状态。
        // 它也是 componentWillReceiveProps 的替代方法。

        // 示例:
        // if (nextProps.userID !== prevState.prevPropsUserID) {
        //    return {
        //        prevPropsUserID: nextProps.userID,
        //        email: nextProps.defaultEmail
        //    };
        // }
        // return null;
    }

    componentDidMount() {

        // 组件装配到 DOM 后立即调用

        // 在这生命周期函数你可以:
        // 获取 DOM 尺寸或位置等、
        // 发送网络请求,从远端加载数据、
        // 实例化第三方库等。

        // 包含了调用者定义的属性。
        this.props

        // 这个特定属性表示组件的开始和结束标记之间的内容。
        this.props.children

        // 表示组件的特定数据的 JavaSript 对象。
        // 若该特定数据不需要在 render() 中使用,可以直接放在实例中,如 this.myData。
        // 应该把 state 作为不可变数据,仅使用 setState() 替换你之前做的改变。
        this.state
    }

    componentWillUnmount() {

        // 组件被卸载和销毁之前立刻调用。

        // 在该方法里处理必要的清理工作,如:
        // 解绑定时器、
        // 解绑事件处理函数、
        // 取消网络请求、
        // 销毁第三方库实例、
        // 清理任何在 componentDidMount 环节创建的 DOM 元素等。
    }

    shouldComponentUpdate(nextProps, nextState) {

        // 当接收到新 props (可能来自父组件)或状态时,其在渲染前被调用,默认返回 true。

        // 返回 false 则 UNSAFE_componentWillUpdate()、render() 和 componentDidUpdate() 将不会被调用。
        // 注意:初始化渲染和使用 forceUpdate() 时候不会调用这方法。
    }

    getSnapshotBeforeUpdate(prevProps, prevState) {

        // 在最新的渲染输出提交给 DOM 前将会立即调用。

        // 该方法可以用于在组件值(包括对应 DOM 的参数,可通过 ref 获得)改变前获取它们,函数返回值将会作为参数传递给 componentDidUpdate(prevProps, prevState, snapshot)。
        // 注意:由于异步渲染,componentWillUpdate 在“渲染”时期,getSnapshotBeforeUpdate 在“提交时期”,componentWillUpdate 读取 DOM 参数将会是滞后的。
    }

    componentDidUpdate(prevProps, prevState, snapshot) {

        // 更新发生后立即被调用。

        // 该方法并不会在初始化渲染时调用。
        // 若 shouldComponentUpdate() 返回false,其将不会被调用。

        // 在这方法中可能做的操作:
        // 操作更新后的 DOM、
        // 对比新旧 props 和 state 后发送网络请求。
    }

    UNSAFE_componentWillMount() {

        // 装配发生前被调用(旧名称为 componentWillMount)。

        // 方法里设置状态不会触发重渲。
        // 注意:该方法推荐使用 constructor() 代替。
    }

    UNSAFE_componentWillReceiveProps(nextProps) {

        // 装配后的组件接收到新 props 时调用(旧名称为 componentWillReceiveProps)。

        // 该方法一般用于根据 this.props 和 nextProps,使用 this.setState() 设置新状态。
        // 注意:该方法推荐使用 static getDerivedStateFromProps() 代替。
    }

    UNSAFE_componentWillUpdate() {

        // 接收到新 props 或 state 后,渲染前调用(旧名称为 componentWillUpdate)。

        // 该方法不会在初始化渲染前调用。
        // 若 shouldComponentUpdate() 返回false,其将不会被调用。
        // 注意:不能在这里调用 this.setState(),很可能会造成死循环。
        // 需要更新状态时应在 static getDerivedStateFromProps(nextProps, prevState) 中完成。
    }

    componentDidCatch(error, info) {

        // 定义该生命周期方法,则该类组件将成为一个错位边界组件。

        // error 是被抛出的错误。
        // info 是一个含有 componentStack 属性的对象。这一属性包含了错误期间关于组件的堆栈信息。

        // 错误边界捕捉发生在它们子组件渲染期间、生命周期方法中和构造函数中的错误,但不能捕捉自己内部的错误。
        // 事件处理器使用普通的 try/catch 即可。

        // 提示:
        //  render() {
        //     if (this.state.hasError) {
        //       // You can render any custom fallback UI
        //       return <h1>Something went wrong.</h1>;
        //     }
        //     return this.props.children;
        //   }
        // 注意:错误边界只用捕获 JavaScript 错误,记录这些错误,并显示回退 UI,不能用于控制流。
    }

    render() {

        // 在此检查 this.props 和 this.state,并返回以下类型之一:
        // React 元素
        // 字符串/数字
        // ReactDOM.createPortal
        // null / boolean (什么都不渲染)

        // 注意:render() 应该是纯净的,不改变组件状态,直接和浏览器交互
        // 提示:可以通过使用一个数组让 render() 返回多个元素(添加 key)
    }
}

// 对于组件中 undefined 的 props 会从这类属性中获取默认值
// 注意:当 props 被设置为 null 时,该属性无效
Example.defaultProps = {};

// props 类型检查,发生在 defaultProps 赋值之后
// 这有助于定位 bug
Example.propTypes = {
    initialText: PropTypes.string
};

// 导出组件对象
export {Example};

版权声明:

本文为博主原创文章,若需转载,须注明出处,添加原文链接。

https://leeguangxing.cn/blog_post_15.html