React.js. Жизненный цикл компонента

27.07.2021

Теги: DOMFrontendJavaScriptReact.jsWeb-разработкаСобытие

Жизненный цикл компонента

Методы жизненного цикла — это специальные методы, которые автоматически вызываются компонентами. Они сообщают о важных вехах в жизни компонента, и их можно использовать, чтобы повлиять на то, что должен сделать компонент. Можно сказать, что это такие обработчики событий, которые вызываются на разных этапах жизни компонента.

componentDidMount()

Этот метод будет вызван лишь раз во всем жизненном цикле данного компонента, сразу после монтирования компонента, после того, как отработал метод render(). В этом методе должны происходить действия, которые требуют доступа к DOM-узлам. Это хорошее место для создания сетевых запросов и для настройки подписок.

В этом методе можно вызывать setState(). Это вызовет дополнительный рендер перед тем, как браузер обновит экран. Гарантируется, что пользователь не увидит промежуточное состояние, даже если render() будет вызываться дважды. Следует использовать этот подход с осторожностью, он может вызвать проблемы с производительностью. В большинстве случаев начальное состояние лучше объявить в constructor().

componentDidUpdate()

componentDidUpdate(prevProps, prevState, snapshot)

Этот метод вызывается после того, как отработал метод render(), но не вызывается при первом рендере. Компонент и все его дочерние компоненты уже перерисовали себя — так что можно работать с DOM. Также подходит для выполнения таких запросов, которые выполняются на основании результата сравнения текущих пропсов с предыдущими. Если пропсы не изменились, новый запрос может и не потребоваться.

componentDidUpdate(prevProps) {
    // популярный пример (не забудьте сравнить пропсы)
    if (this.props.userID !== prevProps.userID) {
        this.fetchData(this.props.userID);
    }
}
В этом методе можно вызывать setState(), однако его необходимо обернуть в условие, как в примере выше, чтобы не возник бесконечный цикл. Вызов setState() влечет за собой дополнительный рендер, который незаметен для пользователя, но может повлиять на производительность компонента. Вместо «отражения» пропсов в состоянии рекомендуется использовать пропсы напрямую.

componentWillUnmount()

Этот метод вызывается непосредственно перед размонтированием и удалением компонента. В этом методе выполняется необходимый сброс — отмена таймеров (setTimeout, setInterval), закрытие сокетов и подписок, созданных в componentDidMount().

Не используйте setState() в этом методе, так как компонент никогда не рендерится повторно. После того, как экземпляр компонента будет размонтирован, он никогда не будет примонтирован снова.

Пример использования

На странице есть три кнопки — «Старт», «Стоп» и «Сбросить». Кнопка «Старт» запускает таймер, который каждую секунду увеличивает счетчик. Кнопка «Стоп» появляется на месте кнопки «Старт» и позволяет остановить таймер. Чтобы не потерять значение счетчика при перезагрузке страницы — значение сохраняется в localStorage. Кнопка «Сбросить» останавливает таймер и сбрасывает значение счетчика, так что можно запустить с нуля.

import React from 'react';

export default class App extends React.Component {
    state = {
        counter: 0,
        isCounting: false,
    };

    handleStart = () => {
        this.timerStart();
        this.setState({isCounting: true});
    }

    handleStop = () => {
        this.timerStop();
        this.setState({isCounting: false});
    }

    handleReset = () => {
        if (this.state.isCounting) {
            this.timerStop();
        }
        this.setState({isCounting: false, counter: 0});
    }
    
    timerStart = () => {
        this.timerId = setInterval(
            () => this.setState(prevState => ({count: prevState.count + 1})),
            1000
        );
    }

    timerStop = () => {
        clearInterval(this.timerId);
    }

    componentDidMount() {
        // если таймер уже запускался, но потом страница была перезагружена
        let reactCounterValue = localStorage.getItem("reactCounterValue");
        if (reactCounterValue !== null) {
            this.setState({counter: parseInt(reactCounterValue)});
        }
    }

    componentDidUpdate() {
        // сохраняем значение счетчика на случай перезагрузки страницы
        localStorage.setItem("reactCounterValue", this.state.counter);
    }

    componentWillUnmount() {
        // останавливаем таймер, чтобы избежать утечки памяти
        this.timerStop();
    }

    render() {
        return (
            <div className="App">
                <h1>React Timer</h1>
                <h3>{this.state.counter}</h3>
                {!this.state.isCounting ? (
                    <button onClick={this.handleStart}>Start</button>
                ) : (
                    <button onClick={this.handleStop}>Stop</button>
                )}
                <button onClick={this.handleReset}>Reset</button>
            </div>
        );
    }
}

Дополнительно

Поиск: DOM • JavaScript • React.js • Web-разработка • Frontend • Событие

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.