Жизненный цикл компонента React в деталях

React.js

В этой статье подробно рассказывается об использовании жизненного цикла React и жизненного цикла каждого этапа, а также подробно демонстрируется пример кода.расположение кода

Без лишних слов, давайте сфотографируем

React生命周期图解

Изображение выше основано на диаграмме жизненного цикла после React 16.4. Если это кажется неправильным, сначала проверьте версию React.


Жизненный цикл React в деталях

Функции жизненного цикла для каждой фазы

конструктор конструктор

Вызывается перед монтированием компонента React, реализуетReact.ComponentКогда конструктор подкласса добавляет super(props) в первую строку.

Конструкторы React обычно используются только для двух целей:

  • путем присвоения объектаthis.stateдля инициализации локальногоstate
  • Привязать метод обработчика событий к экземпляру

Если нет инициализированного состояния (state), и не имеет связанного метода, обычно не требуемого дляReactКомпоненты реализуют конструктор.

Нет необходимости вызывать конструкторsetState(), просто установите начальное состояние наthis.stateВот и все.

static getDerivedStateFromProps(nextProps, prevState)

getDerivedStateFromPropsВызывается перед каждым вызовом метода рендеринга. Включая инициализацию и последующие обновления.

Содержит два параметра: первый параметр подлежит обновлениюpropsзначение, второй параметр является предыдущимstateстоимость

Возвращаемое значение: вернуть какnull, без каких-либо побочных эффектов. Если вы хотите обновить некоторыеstateзначение состояния, то возвращается объект, который будетstateмодифицировать

Жизненный цикл — это статическая функция, принадлежащая методу класса и не находящаяся в его области видимости.thisиз

render()

render()Метод является единственным обязательным методом в компоненте класса, а остальную часть жизненного цикла писать не требуется. Когда компонент визуализируется, он переходит к этому жизненному циклу, а отображаемые компоненты определяются возвращаемым значением жизненного цикла render().

Уведомление:Если метод shouldComponentUpdate() возвращает false, render() вызываться не будет.

componentDidMount()

Вызывается сразу после монтирования компонента React (вставки в дерево).

Жизненный цикл componentDidMount — хорошее время для отправки сетевых запросов и включения прослушивания событий.

При необходимости setState() можно вызвать сразу в этом жизненном цикле.

shouldComponentUpdate(nextProps, nextState)

Вызывается до того, как компонент будет готов к обновлению, вы можете контролировать, обновляется ли компонент, возвращать true, когда компонент обновляется, и возвращать false, когда компонент не обновляется.

Содержит два параметра, первый — это значение реквизита, которое нужно обновить, второй — значение состояния, которое нужно обновить, вы можете судить на основе реквизита или состояния до и после обновления, решить, следует ли обновлять, и выполнить оптимизацию производительности.

не хочуshouldComponentUpdateВызовите setState() в , иначе это вызовет бесконечный цикл вызова обновления и рендеринга, пока память браузера не выйдет из строя.

getSnapshotBeforeUpdate(prevProps, prevState)

getSnapshotBeforeUpdate()Вызывается перед фиксацией самого последнего вывода рендеринга. То есть после рендера, когда компонент вот-вот будет смонтирован.

Это позволяет компоненту собирать некоторую информацию (например, положение прокрутки) до фактического обновления DOM, любое значение, возвращаемое этим жизненным циклом, передается в качестве параметра вcomponentDidUpdate(). Возвращает null, если не нужно передавать значение

componentDidUpdate(prevProps, prevState, snapshot)

componentDidUpdate()Вызывается сразу после обновления. Этот жизненный цикл не запускается при первом отображении компонента.

setState() можно вызывать в течение этого жизненного цикла, нодолжен быть включен в условный оператор, в противном случае это вызовет бесконечный цикл и в конечном итоге приведет к сбою памяти браузера.

componentWillUnmount()

componentWillUnmount()Вызывается, когда компонент собирается быть размонтированным или уничтоженным.

Этот жизненный цикл являетсяотменить сетевой запрос, Удалитьпрослушать событие,Очистить элементы DOM,таймер очисткиОжидание подходящего времени для работы

Уведомление:componentWillMount(), componentWillUpdate(), componentWillReceiveProps() скоро устаревают, пожалуйста, не используйте их в компонентах. Поэтому в этой статье это не объясняется, чтобы избежать путаницы.

порядок выполнения жизненного цикла

при установке

  • constructor()

  • static getDerivedStateFromProps()

  • render()

  • componentDidMount()

При обновлении

  • static getDerivedStateFromProps()

  • shouldComponentUpdate()

  • render()

  • getSnapshotBeforeUpdate()

  • componentDidUpdate()

при удалении

  • componentWillUnmount()

Можно ли вызывать setState() в жизненном цикле

инициализировать состояние

  • constructor()

можно вызвать setState()

  • componentDidMount()

SetState() может быть вызван в соответствии с условием суждения

  • componentDidUpdate()

Запретить вызов setState()

  • shouldComponentUpdate()

  • render()

  • getSnapshotBeforeUpdate()

  • componentWillUnmount()


Пример демонстрации

Адрес источника

Ниже приводится понимание порядка выполнения каждого жизненного цикла на основе изменения реквизита, изменения состояния родительско-дочернего компонента и монтирования/выгрузки дочерних компонентов.Заинтересованные учащиеся могут посмотреть вместе или загрузить код на испытайте это сами.

написать код компонента

Родительский компонент: Parent.js

import React, { Component } from 'react';

import Child from './Child.js';

const parentStyle = {
    padding: 40,
    margin: 20,
    border: '1px solid pink'
}

const TAG = "Parent 组件:"

export default class Parent extends Component {

    constructor(props) {
        super(props);
        console.log(TAG, 'constructor');
        this.state = {
            num: 0,
            mountChild: true
        }
    }

    static getDerivedStateFromProps(nextProps, prevState) {
        console.log(TAG, 'getDerivedStateFromProps');
        return null;
    }

    componentDidMount() {
        console.log(TAG, 'componentDidMount');
    }

    shouldComponentUpdate(nextProps, nextState) {
        console.log(TAG, 'shouldComponentUpdate');
        return true;
    }

    getSnapshotBeforeUpdate(prevProps, prevState) {
        console.log(TAG, 'getSnapshotBeforeUpdate');
        return null;
    }
    
    componentDidUpdate(prevProps, prevState, snapshot) {
        console.log(TAG, 'componentDidUpdate');
    }

    componentWillUnmount() {
        console.log(TAG, 'componentWillUnmount');
    }


    /**
     * 修改传给子组件属性 num 的方法
     */
    changeNum = () => {
        let { num } = this.state;
        this.setState({
            num: ++ num
        });
    }

    /**
     * 切换子组件挂载和卸载的方法
     */
    toggleMountChild = () => {
        let { mountChild } = this.state;
        this.setState({
            mountChild: !mountChild
        });
    }

    render() {
        console.log(TAG, 'render');
        const { num, mountChild } = this.state;
        return (
            <div style={ parentStyle }>
                <div>
                    <p>父组件</p>
                    <button onClick={ this.changeNum }>改变传给子组件的属性 num</button>
                    <br />
                    <br />
                    <button onClick={ this.toggleMountChild }>卸载 / 挂载子组件</button>
                </div>
                {
                    mountChild ? <Child num={ num } /> : null
                }
            </div>
        )
    }
}

Дочерний компонент: Child.js

import React, { Component } from 'react'


const childStyle = {
    padding: 20,
    margin: 20,
    border: '1px solid black'
}

const TAG = 'Child 组件:'

export default class Child extends Component {

    constructor(props) {
        super(props);
        console.log(TAG, 'constructor');
        this.state = {
            counter: 0
        };
    }

    static getDerivedStateFromProps(nextProps, prevState) {
        console.log(TAG, 'getDerivedStateFromProps');
        return null;
    }

    componentDidMount() {
        console.log(TAG, 'componentDidMount');
    }

    shouldComponentUpdate(nextProps, nextState) {
        console.log(TAG, 'shouldComponentUpdate');
        return true;
    }

    getSnapshotBeforeUpdate(prevProps, prevState) {
        console.log(TAG, 'getSnapshotBeforeUpdate');
        return null;
    }
    
    componentDidUpdate(prevProps, prevState, snapshot) {
        console.log(TAG, 'componentDidUpdate');
    }

    componentWillUnmount() {
        console.log(TAG, 'componentWillUnmount');
    }

    changeCounter = () => {
        let { counter }= this.state;
        this.setState({
            counter: ++ counter
        });
    }

    render() {
        console.log(TAG, 'render');
        const { num } = this.props;
        const { counter } = this.state;
        return (
            <div style={ childStyle }>
                <p>子组件</p>
                <p>父组件传过来的属性 num : { num }</p>
                <p>自身状态 counter : { counter }</p>
                <button onClick={ this.changeCounter }>改变自身状态 counter</button>
            </div>
        )
    }
}

Исследуйте порядок выполнения жизненного цикла по времени изменения состояния пяти компонентов.

1. Инициализация родительского и дочернего компонентов

Когда родительско-дочерний компонент визуализируется и загружается в первый раз, интерфейс отображается как:

初始化展示界面

Порядок печати журнала в консоли:

  • Родительский компонент: конструктор()
  • Родительский компонент: getDerivedStateFromProps()
  • Родительский компонент: рендер()
  • Дочерний компонент: конструктор()
  • Дочерний компонент: getDerivedStateFromProps()
  • Дочерний компонент: рендер()
  • Дочерний компонент: componentDidMount()
  • Родительский компонент: componentDidMount()

2. При изменении состояния самого дочернего компонента

Щелкните дочерний компонентизменить собственное состояниекнопка, интерфейсСчетчик самоуправления:Значение will + 1, и порядок печати журнала в консоли:

  • Дочерний компонент: getDerivedStateFromProps()
  • Дочерний компонент: shouldComponentUpdate()
  • Дочерний компонент: рендер()
  • Дочерний компонент: getSnapshotBeforeUpdate()
  • Дочерний компонент: componentDidUpdate()

3. При изменении реквизита, переданного в дочерний компонент в родительском компоненте

Щелкните родительский компонентИзмените номер свойства, переданный дочернему компонентукнопка, интерфейсАтрибут num, переданный от родительского компонента:Значение will + 1, и порядок печати журнала в консоли:

  • Родительский компонент: getDerivedStateFromProps()
  • Родительский компонент: shouldComponentUpdate()
  • Родительский компонент: рендер()
  • Дочерний компонент: getDerivedStateFromProps()
  • Дочерний компонент: shouldComponentUpdate()
  • Дочерний компонент: рендер()
  • Дочерний компонент: getSnapshotBeforeUpdate()
  • Родительский компонент: getSnapshotBeforeUpdate()
  • Дочерний компонент: componentDidUpdate()
  • Родительский компонент: componentDidUpdate()

4. Удалить подкомпоненты

Щелкните родительский компонентРазмонтировать/смонтировать подкомпоненткнопки, подкомпоненты в интерфейсе исчезнут, а порядок печати журнала в консоли будет таким:

  • Родительский компонент: getDerivedStateFromProps()
  • Родительский компонент: shouldComponentUpdate()
  • Родительский компонент: рендер()
  • Родительский компонент: getSnapshotBeforeUpdate()
  • Дочерний компонент: componentWillUnmount()
  • Родительский компонент: componentDidUpdate()

5. Перемонтируйте подкомпоненты

Нажмите еще раз в родительском компонентеРазмонтировать/смонтировать подкомпоненткнопка, подкомпоненты в интерфейсе будут перерисованы, а порядок печати журнала в консоли будет следующим:

  • Родительский компонент: getDerivedStateFromProps()
  • Родительский компонент: shouldComponentUpdate()
  • Родительский компонент: рендер()
  • Дочерний компонент: конструктор()
  • Дочерний компонент: getDerivedStateFromProps()
  • Дочерний компонент: рендер()
  • Родительский компонент: getSnapshotBeforeUpdate()
  • Дочерний компонент: componentDidMount()
  • Родительский компонент: componentDidUpdate()

Сводка порядка выполнения жизненного цикла родительско-дочернего компонента:

  • При изменении состояния дочернего компонента родительский компонент не будет обновляться без каких-либо побочных эффектов на родительский компонент, то есть жизненный цикл родительского компонента не будет запущен

  • Когда состояние родительского компонента изменяется (включая монтирование дочернего компонента), это запускает соответствующий жизненный цикл и обновление дочернего компонента.

    • рендеринг и жизненный цикл перед рендерингом, родительский компонент выполняется первым

    • рендер и цикл объявления после рендера, дочерний компонент выполняется первым, и он выполняется поочередно с родительским компонентом

  • Когда дочерний компонент размонтирован, будет выполнен только его собственный жизненный цикл componentWillUnmount, и никакие другие жизненные циклы не будут запущены.

Это может быть не очень хорошо и не очень полно. Просто общее резюме. Что-то не так, надеюсь, вы меня поправите.


Загрузка примера кода

Адрес источника(Добро пожаловать, Звезда, спасибо!)

Не видели достаточно? Перейти к:Официальный сайт компонента React