Учебный курс по React, часть 19: методы жизненного цикла компонентов +21


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

image

> Часть 1: обзор курса, причины популярности React, ReactDOM и JSX
> Часть 2: функциональные компоненты
> Часть 3: файлы компонентов, структура проектов
> Часть 4: родительские и дочерние компоненты
> Часть 5: начало работы над TODO-приложением, основы стилизации
> Часть 6: о некоторых особенностях курса, JSX и JavaScript
> Часть 7: встроенные стили
> Часть 8: продолжение работы над TODO-приложением, знакомство со свойствами компонентов
> Часть 9: свойства компонентов
> Часть 10: практикум по работе со свойствами компонентов и стилизации
> Часть 11: динамическое формирование разметки и метод массивов map
> Часть 12: практикум, третий этап работы над TODO-приложением
> Часть 13: компоненты, основанные на классах
> Часть 14: практикум по компонентам, основанным на классах, состояние компонентов
> Часть 15: практикумы по работе с состоянием компонентов
> Часть 16: четвёртый этап работы над TODO-приложением, обработка событий
> Часть 17: пятый этап работы над TODO-приложением, модификация состояния компонентов
> Часть 18: шестой этап работы над TODO-приложением
> Часть 19: методы жизненного цикла компонентов
> Часть 20: первое занятие по условному рендерингу


Занятие 34. Методы жизненного цикла компонентов, часть 1


> Оригинал

Одной из особенностей разработки React-приложений является тот факт, что мы пишем довольно простой JavaScript-код, который приводит в действие внутренние механизмы React и тем самым даёт нам замечательные возможности по разработке интерфейсов приложений и по работе с данными. При этом компоненты, которыми мы пользуемся, в течение своего жизненного цикла, проходят через определённые этапы. Часто то, что происходит с компонентом в приложении, сравнивают с жизнью человека. Люди рождаются, живут, в их жизни случаются некие значимые события, после чего они умирают. Компоненты React в этом похожи на людей, так как они тоже «рождаются», «живут» и «умирают». Работая с компонентами, мы можем реагировать на то, что с ними происходит, благодаря методам их жизненного цикла, которые вызываются в особенные моменты их «жизни».

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

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

Вот хороший материал, посвящённый методам жизненного цикла компонентов React, которые были актуальны до выхода версии React 16.3. Здесь, в публикации из официального блога разработчиков React, можно узнать об изменениях, которые произошли в React 16.3.

Теперь начнём разговор о методах жизненного цикла компонентов React, с которыми вам придётся встречаться чаще всего.

Мы, как всегда, будем пользоваться здесь демонстрационным проектом. В данном случае мы начинаем со стандартного проекта, созданного средствами create-react-app, в файле App.js которого содержится следующий код:

import React, {Component} from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {}
    }
    
    render() {
        return (
            <div>
                Code goes here
            </div>
        )
    }
}

export default App

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

Часто его, говоря о методах жизненного цикла компонентов, не упоминают. Думаю, что этот метод, если сравнивать компонент с человеком, можно сравнить с одеванием перед выходом на улицу. Задачей этого метода является определение того, что будет выведено на экран, то есть того, как будет выглядеть компонент. Метод render() в процессе жизни компонента может быть вызван множество раз. Так, когда React определяет, что что-то, относящееся к компоненту, изменилось, наподобие состояния или свойств, то есть что-то такое, что может повлиять на внешний вид компонента, React может вызвать этот метод. Это можно сравнить, если продолжить аналогию с людьми, с тем, что человек может решить переодеться. Например для того, чтобы, после рабочего дня, подготовиться к некоему праздничному мероприятию.

Теперь рассмотрим ещё один метод жизненного цикла компонентов — componentDidMount(). Этот метод объявляют, точно так же, как и любые другие методы компонентов, основанных на классах, в теле класса компонента:

componentDidMount() {
}

Этот метод вызывается в момент жизненного цикла компонента, который можно сравнить с «рождением» этого компонента. Этот метод срабатывает один раз после того, как компонент будет смонтирован (вставлен) в дерево DOM. При этом, например, если после изменения неких данных, влияющих на внешний вид компонента, будет выполнен его повторный рендеринг, метод componentDidMount() вызван не будет. Происходит это из-за того, что при выполнении подобных операций не производится изъятие компонента из дерева DOM и его последующее повторное включение в состав дерева.

Метод componentDidMount() обычно используют для выполнения обращений к неким API, в случаях, когда разработчику нужны данные из внешних источников. Предположим, компонент, который мы тут рассматриваем, на самом деле называется TodoList и представляет собой компонент, формирующий список дел в Todo-приложении. Метод componentDidMount() такого компонента может выполнять загрузку материалов из серверной базы данных, необходимых для корректного вывода на страницу хранящегося на сервере списка дел. В результате после того, как монтирование компонента завершено, мы, в методе componentDidMount(), можем загрузить данные, необходимые для правильного отображения компонента на странице. Мы ещё поговорим о загрузке данных, необходимых компонентам, а пока же можете запомнить, что это — наиболее часто встречающийся вариант использования метода componentDidMount().

Следующий метод жизненного цикла компонентов, который мы обсудим, называется componentWillReceiveProps(). Этот метод можно сравнить с тем, что происходит, когда кто-то получает от кого-то подарок. Так, компонент может получать свойства от родительского компонента. Каждый раз, когда компонент принимает свойства, вызывается этот метод. При этом данный метод вызывается каждый раз, когда родительский компонент передаёт свойства дочернему компоненту, а не только тогда, когда это случается в первый раз. Например, если родительский компонент решит поменять свойства, переданные дочернему компоненту, то мы, в методе componentWillReceiveProps(), сможем, например, проверить, отличаются ли новые свойства от тех, что уже были переданы компоненту. Дело в том, что если новые свойства не отличаются от старых, это значит, что их поступление ничего не меняет, а значит — мы можем, выяснив это, больше ничего не делать. Если же новые свойства отличаются от старых, мы можем выполнить некие действия. Обычно этот метод объявляют в теле класса компонента в таком виде:

componentWillReceiveProps(nextProps) {
}

Тут обычно используется, в качестве имени параметра, nextProps, но назвать этот параметр можно как угодно. Для того чтобы сравнить некое конкретное свойство, которое уже было передано компоненту, с тем, что уже было ему передано ранее, и принять решение о дальнейших действиях, можно воспользоваться такой конструкцией:

componentWillReceiveProps(nextProps) {
    if (nextProps.whatever !== this.props.whatever) {
        // сделать тут что-то важное
    }
}

Обычно этот метод используют именно так.

Однако, как уже было сказано, после выхода React 16.3 некоторые методы жизненного цикла компонентов были признаны устаревшими, и componentWillReceiveProps() — это один из таких методов.

До выхода React 17 этими устаревшими методами всё ещё можно пользоваться, хотя лучше этого не делать. Если без рассматриваемого метода никак не обойтись — его нужно назвать UNSAFE_componentWillReceiveProps(). После выхода React 17 имя метода componentWillReceiveProps() не будет означать ничего особенного.

Об этом методе полезно знать для того, чтобы иметь возможность понимать устаревший код, но при разработке современных React-приложений он уже использоваться не будет.

Ещё один интересный метод жизненного цикла компонентов называется shouldComponentUpdate(). Он, если продолжить сравнение компонента с человеком, напоминает момент, когда человек размышляет о том, надо ли ему переодеться или нет. В обычных условиях, если React не вполне уверен в том, надо ли повторно отрендерить компонент, он его, на всякий случай, всё же отрендерит. При этом неважно — нужно ли это, в соответствии с логикой приложения, или нет.

Это приводит к тому, что React повторно рендерит компоненты даже в тех случаях, когда ничего, имеющего отношение к компоненту, не меняется. Подобное может привести к замедлению приложения, так как по такому принципу React обрабатывает все компоненты, входящие в состав приложения. Метод shouldComponentUpdate() даёт разработчику возможность оптимизировать приложение. Здесь можно реализовать некую логику, помогающую выяснить необходимость обновления компонента. Этот метод обычно объявляют так:

shouldComponentUpdate(nextProps, nextState) {
    // вернуть true если компонент нуждается в обновлении
    // вернуть false в противном случае
}

При этом из этого метода, если компонент нуждается в повторном рендеринге, с учётом новых свойств и состояния, нужно вернуть true. В противном случае из него нужно вернуть false. Собственно говоря, возврат false из этого метода приводит к тому, что обновление компонента не выполняется и приложение работает быстрее, но, делая это, нужно быть уверенным в том, что компоненту действительно не требуется повторный рендеринг. Если же компоненту нужно обновиться, а этот метод вернул false — это приведёт к появлению ошибок, с которыми будет сложно бороться.

Ещё один метод жизненного цикла компонентов, о котором мы поговорим, называется componentWillUnmount(). Этот метод знаменует собой окончание «жизни» компонента — тот момент, когда он удаляется из дерева DOM и исчезает с экрана.

Этот метод, в основном, используется для того, чтобы освобождать ресурсы, занятые компонентом и навести перед его удалением порядок. Например, если в методе componentDidMount() было настроено нечто вроде прослушивателя событий, благодаря которому, когда пользователь прокручивает страницу, выполняется некий код, именно в componentWillUnmount() можно удалить такой прослушиватель событий. На самом же деле, у этого метода есть множество вариантов применения, которые направлены на то, чтобы убрать из приложения всё, что окажется ненужным после исчезновения компонента.

Вот полный код нашего компонента App, в который добавлены методы жизненного цикла:

import React, {Component} from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {}
    }
    
    componentDidMount() {
        // загрузить данные, необходимые для корректного отображения компонента
    }
    
    componentWillReceiveProps(nextProps) {
        if (nextProps.whatever !== this.props.whatever) {
            // сделать тут что-то важное
        }
    }
    
    shouldComponentUpdate(nextProps, nextState) {
        // вернуть true если компонент нуждается в обновлении
        // вернуть false в противном случае
    }
    
    componentWillUnmount() {
        // навести порядок после удаления компонента
        // (например - убрать прослушиватели событий)
    }
    
    render() {
        return (
            <div>
                Code goes here
            </div>
        )
    }
}

export default App

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

Занятие 35. Методы жизненного цикла компонентов, часть 2


> Оригинал

Как уже было сказано на предыдущем занятии, когда вышел React 16.3, было сообщено о том, что три метода жизненного цикла компонентов устарели. Это методы componentWillMount(), componentWillReceiveProps() и componentWillUpdate(). Также было сообщено о появлении двух новых методов. Это — статический метод getDerivedStateFromProps() и метод getSnapshotBeforeUpdate(). Нельзя сказать, что эти методы сыграют важную роль на будущих занятиях этого курса, но мы, несмотря на это, здесь с ними ознакомимся.

Экспериментировать будем в том же проекте, который мы использовали в прошлый раз.

Вот как выглядит объявление метода getDerivedStateFromProps():

static getDerivedStateFromProps(props, state) {
}

Обратите внимание на ключевое слово static перед именем метода. Он, на основании принятых им свойств, должен возвратить обновлённое состояние. Он используется в тех случаях, когда некий компонент должен принимать входящие свойства, получаемые им от компонента-родителя, и настраивать своё состояние, основываясь на этих свойствах. Подробности об этом методе можно почитать здесь. В этом материале, опубликованном в блоге React, речь идёт о том, что применение этого метода оправдано далеко не во всех тех ситуациях, в которых он, как кажется, может пригодиться. Его неправильное использование может приводить к различным ошибкам, к падению производительности приложений, поэтому пользоваться им следует с осторожностью. Не следует пытаться решать с его помощью задачи, для решения которых он не предназначен. Вот документация к этому методу.

Теперь поговорим о методе getSnapshotBeforeUpdate(). Вот как выглядит его объявление в теле класса:

getSnapshotBeforeUpdate() {
}

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

Итоги


Сегодня мы поговорили о методах жизненного цикла компонентов. Когда вы продвинетесь в деле разработки React-приложений, они вам, безусловно, пригодятся. На дальнейших занятиях этого курса мы ещё встретимся с этими методами, в частности, с componentDidMount(). В следующий раз поговорим об условном рендеринге.

Уважаемые читатели! Если вы профессионально разрабатываете React-приложения — просим рассказать о том, как вы пользуетесь методами жизненного цикла компонентов.




К сожалению, не доступен сервер mySQL