жизненный цикл приложения react

Состояние и жизненный цикл

На этой странице представлена концепция состояния и жизненного цикла в компоненте React. Здесь вы можете найти подробный справочник API компонента.

Рассмотрим пример тикающих часов из одного из предыдущих разделов. В разделе Отрисовка элементов мы изучили только один способ обновления пользовательского интерфейса (UI). Мы вызываем ReactDOM.render() для изменения отрисованного вывода:

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

Мы можем начать с инкапсуляции кода в функциональный компонент часов:

В идеале мы хотим написать это один раз и иметь само обновление Clock :

Состояние похоже на свойство, но оно является закрытым и полностью контролируется компонентом.

Мы упоминали ранее, что компоненты, определённые как классы, имеют некоторые дополнительные возможности. Локальное состояние — это как раз одно из них: эта возможность доступна только классам.

Преобразование функции в класс

Удалить оставшиеся пустое объявление функции.

Clock теперь определён как класс, а не функция.

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

Добавление локального состояния в класс

Мы переместим date из свойств в состояние за три шага:

Обратите внимание, что мы передаём props базовому (родительскому) конструктору:

Позже мы добавим код таймера обратно к самому компоненту.

Результат выглядит следующим образом:

Затем мы позволим настроить Clock собственным таймером с обновлением каждую секунду.

Добавление методов жизненного цикла в класс

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

Мы хотим настроить таймер всякий раз, когда Clock отрисовывается в DOM в первый раз. Это называется «монтированием» (установкой) в React.

Мы можем объявить специальные методы в классе-компоненте для выполнения кода, когда компонент устанавливается и удаляется:

Эти методы называются “хуками (методами) жизненного цикла”.

Хук componentDidMount() запускается после того, как вывод компонента отрисован в DOM. Это хорошее место для установки таймера:

Хотя this.props настраивается самим React, и у this.state есть специальное значение, вы можете добавлять дополнительные поля в класс вручную, если вам нужно сохранить что-то, что не участвует в при выводе данных (например, идентификатор таймера).

Мы удалим таймер в хуке жизненного цикла componentWillUnmount() :

Он будет использовать this.setState() для планирования обновлений локального состояния компонента:

Теперь часы тикают каждую секунду.

Давайте быстро повторим, что происходит, а также перечислим порядок, в котором вызываются методы:

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

Не изменяйте напрямую состояние

Например, это не приведёт к повторной отрисовке компонента:

Вместо этого используйте setState() :

Обновления состояния могут быть асинхронными

React может выполнять несколько вызовов setState() за одно обновление для лучшей производительности.

Поскольку this.props и this.state могут обновляться асинхронно, вы не должны полагаться на их значения для вычисления следующего состояния.

Например, этот код может не обновить счётчик:

Мы использовали стрелочную функцию выше, но это также работает с обычными функциями:

Обновления состояния объединяются

Например, ваше состояние может содержать несколько независимых переменных:

Затем вы можете самостоятельно их обновлять с помощью отдельных вызовов setState() :

Однонаправленный поток данных

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

Вот почему состояние часто называют локальным или инкапсулированным. Оно недоступно для любого компонента, за исключением того, который владеет и устанавливает его.

Компонент может передать своё состояние вниз по дереву компонентов в виде свойства его дочерних компонентов:

Это также работает для пользовательских компонентов:

Это обычно называют потоком данных «сверху вниз» или «однонаправленным потоком данных». Любое состояние всегда принадлежит определённому компоненту, а любые данные или пользовательский интерфейс, полученные из этого состояния, могут влиять только на компоненты, находящиеся «ниже» в их дереве компонентов.

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

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

Источник

Состояние и жизненный цикл

На этой странице представлены понятия «состояние» (state) и «жизненный цикл» (lifecycle) React-компонентов. Подробный справочник API компонентов находится по этой ссылке.

В качестве примера рассмотрим идущие часы из предыдущего раздела. В главе Рендеринг элементов мы научились обновлять UI только одним способом — вызовом ReactDOM.render() :

Для начала, извлечём компонент, показывающий время:

В идеале мы бы хотели реализовать Clock таким образом, чтобы компонент сам себя обновлял:

«Состояние» очень похоже на уже знакомые нам пропсы, отличие в том, что состояние контролируется и доступно только конкретному компоненту.

Преобразование функционального компонента в классовый

Давайте преобразуем функциональный компонент Clock в классовый компонент за 5 шагов:

Теперь Clock определён как класс, а не функция.

Метод render будет вызываться каждый раз, когда происходит обновление. Так как мы рендерим в один и тот же DOM-контейнер, мы используем единственный экземпляр класса Clock — поэтому мы можем задействовать внутреннее состояние и методы жизненного цикла.

Добавим внутреннее состояние в класс

Переместим date из пропсов в состояние в три этапа:

Обратите внимание, что мы передаём props базовому (родительскому) конструктору:

Позже мы вернём код таймера обратно и на этот раз поместим его в сам компонент.

Результат выглядит следующим образом:

Теперь осталось только установить собственный таймер внутри Clock и обновлять компонент каждую секунду.

Добавим методы жизненного цикла в класс

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

Первоначальный рендеринг компонента в DOM называется «монтирование» (mounting). Нам нужно устанавливать таймер всякий раз, когда это происходит.

Каждый раз когда DOM-узел, созданный компонентом, удаляется, происходит «размонтирование» (unmounting). Чтобы избежать утечки ресурсов, мы будем сбрасывать таймер при каждом «размонтировании».

Объявим специальные методы, которые компонент будет вызывать при монтировании и размонтировании:

Эти методы называются «методами жизненного цикла» (lifecycle methods).

Метод componentDidMount() запускается после того, как компонент отрендерился в DOM — здесь мы и установим таймер:

Обратите внимание, что мы сохраняем ID таймера в this ( this.timerID ).

Поля this.props и this.state в классах — особенные, и их устанавливает сам React. Вы можете вручную добавить новые поля, если компоненту нужно хранить дополнительную информацию (например, ID таймера).

Теперь нам осталось сбросить таймер в методе жизненного цикла componentWillUnmount() :

this.setState() планирует обновление внутреннего состояния компонента:

Теперь часы обновляются каждую секунду.

Давайте рассмотрим наше решение и разберём порядок, в котором вызываются методы:

Как правильно использовать состояние

Не изменяйте состояние напрямую

В следующем примере повторного рендера не происходит:

Вместо этого используйте setState() :

Конструктор — это единственное место, где вы можете присвоить значение this.state напрямую.

Обновления состояния могут быть асинхронными

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

Поскольку this.props и this.state могут обновляться асинхронно, вы не должны полагаться на их текущее значение для вычисления следующего состояния.

Например, следующий код может не обновить счётчик:

В данном примере мы использовали стрелочную функцию, но можно использовать и обычные функции:

Обновления состояния объединяются

Например, состояние может состоять из нескольких независимых полей:

Их можно обновлять по отдельности с помощью отдельных вызовов setState() :

Однонаправленный поток данных

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

Состояние часто называют «локальным», «внутренним» или инкапсулированным. Оно доступно только для самого компонента и скрыто от других.

Компонент может передать своё состояние вниз по дереву в виде пропсов дочерних компонентов:

Это, в общем, называется «нисходящим» («top-down») или «однонаправленным» («unidirectional») потоком данных. Состояние всегда принадлежит определённому компоненту, а любые производные этого состояния могут влиять только на компоненты, находящиеся «ниже» в дереве компонентов.

Если представить иерархию компонентов как водопад пропсов, то состояние каждого компонента похоже на дополнительный источник, который сливается с водопадом в произвольной точке, но также течёт вниз.

У каждого компонента Clock есть собственное состояние таймера, которое обновляется независимо от других компонентов.

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

Источник

Жизненный цикл приложения react

Урок 2 — Компоненты

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

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

Есть всего 4 сценария, когда методы жизненного цикла могут быть использованы:

Инициализация компонента (первый render)

При первом render компонента методы жизненного цикла будут вызваны в таком порядке:

жизненный цикл приложения react

Изменение параметров ( props )

Когда от родительского компонента приходят измененные параметры, последовательность вызова методов жизненного цикла такая:

жизненный цикл приложения react

Изменение состояния (вызов setState )

Когда в компоненте изменяется состояние, то методы жизненного цикла вызываются в таком порядке:

жизненный цикл приложения react

Удаление компонента

Перед удаление компонента из DOM будет вызван один-единственный метод сomponentWillUnmount

жизненный цикл приложения react

Методы жизненного цикла

getDefaultProps

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

getInitialState

Создан для определения начального состояния компонента.

componentWillMount

Вызывается один раз прямо перед тем, как состоится первый render компонента. Вызов setState в рамках данного метода дополнительного рендера не вызовет.

componentDidMount

Вызывается один раз прямо сразу после того, как состоялся первый render компонента.

componentWillReceiveProps

Вызывается каждый раз, когда компонент получает новые параметры. Не вызывается для первого рендера. Вызов setState в рамках данного метода дополнительного рендера не вызовет.

shouldComponentUpdate

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

componentWillUpdate

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

. Не используйте setState() в этом методе! Так у вас может произойти зацикливание!

componentDidUpdate

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

Произведенные изменения уже отображены в DOM дереве. Обычно, в данном методе производят какие-то операции с DOM елементами согласно изменениям.

. Не используйте setState() в этом методе! Так у вас может произойти зацикливание!

componentWillUnmount

Вызывается перед тем, как компонент будет удален из DOM.

Весь жизненный цикл компонента можно представить в виде такой схемы

жизненный цикл приложения react

Иногда вместо того, чтобы писать так:

Очень хочется написать так:

Refs (string attribute or callbacks)

Атрибут ref может быть callback функцией, которая будет немедленно исполнена, после того как компонент будет установлен. Указанный компонент будет передан в качестве параметра, и функция обратного вызова может сразу использовать компонент, или сохранить ссылки для дальнейшего использования. Стоит отметить что, при прикреплении ref на компонент DOM, такой как тег

React так же поддерживает использование строки (вместо обратного вызова):

Но стоит отметить тот факт что в документации разработчики утверждают что string refs считаются устаревшими. Рефы обратного вызова являются предпочтительными.

Как работают события в React

Если на странице есть 100 (или 1000) различных элементов, на которых вы назначили обработчики события onClick — React вместо того, чтобы назначать обработчик каждому, поставит только один обработчик на их общего предка, а там, уже с помощью всплытия, поймет на каком именно потомке произошло событие и обработает его. Такой подход упрощает инициализацию и экономит память.

жизненный цикл приложения react

Вопросы для самопроверки

Установка node и npm

Установка и использование http-server

Задание 1: Сделать выбор цвета для заметки

Уровень сложности: низкий

При создании новой заметки реализовать выбор ее цвета. Можно выбирать из всего спектра ( ) или использовать только 5–7 ваших любимых цветов (как в Google Keep).

Задание 2: Таймер

Уровень сложности: средний

Нужно усовершенствовать написанный таймер добавлением в него кнопок «Пауза», «Старт» и «Возобновить».

Задание 3: Поиск по заметкам

Уровень сложности: средний

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

Задание 4: To-do list

Уровень сложности: высокий

Написать список задач. Пользователь может добавить новую задачу, отметить ее как выполненную (просто вычеркнуть ее из списка) и фильтры «Все», «Завершенные» и «Новые». Задачи должны сохраняться в localStorage.

Если есть вопросы пишите сюда

Источник

Понимание жизненного цикла React-компонента

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

Update:

В React 16.3 появились два дополнительных метода жизненного цикла и несколько методов объявлено устаревшими, подробности по ссылке.
(Прим. переводчика: Хотя некоторые методы и объявлены устаревшими, их описание, на мой взгляд, все равно будет полезно, хотя бы тем разработчикам, которые работают с предыдущими версиями React и в целом для понимания вместо каких методов и для чего были введены новые. Статью по ссылке добавил ниже)

Конструкторы являются основной ООП – это такая специальная функция, которая будет вызываться всякий раз, когда создается новый объект. Очень важно вызывать функцию super в случаях, когда наш класс расширяет поведение другого класса, который имеет конструктор. Выполнение этой специальной функции будет вызывать конструктор нашего родительского класса и разрешать ему проинициализировать себя. Вот почему мы имеем доступ к this.props только после вызова super. (имеется ввиду вызов super(props) в классе-наследнике React.Component)

Поэтому конструкторы — это отличное место для инициализации компонента – создание любых полей (переменные начинающиеся с this.) или инициализации состояния компонента на основе полученных props.

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

componentWillMount не очень отличается от конструктора – она также вызывается лишь раз в изначальном жизненном цикле. Вообще исторически были некоторые причины использовать componentWillMount поверх конструктора — смотри react-redux issue, но на данный момент практика, описанная там, устарела.

У многих возможно появится соблазн использовать эту функцию для отправки реквеста на получение данных и они будут ожидать, что данные будут доступны прежде чем отработает изначальный render. Но это не тот случай – хотя реквест и будет инициализирован перед render, он не успеет выполниться прежде чем render будет вызван.

Кроме того, с изменениями в React Fiber (после релиза React 16 beta) эта функция может быть вызвана несколько раз перед вызовом изначального render, что может привести к различным побочным эффектам, связанным с этим. Поэтому, не рекомендуется использовать эту функцию для выполнения любых операций вызывающих сайд-эффекты.

Также важно отметить, что эта функция вызывается, когда используется рендеринг на стороне сервера (server side rendering), когда ее антипод – componentDidMount не будет вызван на сервере, но будет на клиенте. Поэтому если некоторый сайд-эффект нацелен на серверную часть, эта функция может быть использована как исключение.

И наконец функция setState может быть свободно использована и не будет вызывать перерисовку компонента.

Эта функция будет вызываться при каждом апдейт жизненном цикле, который будет происходить при изменениях в props (когда перерисовывается родительский компонент) и будет принимать маппинг всех передаваемых props, не важно изменялось значение какого-либо свойства или нет с предыдущей фазы перерисовки.

Эта функция будет идеальна, если у вас есть какой-нибудь компонент, часть состояния которого (state), зависит от props передаваемых от родительского компонента, т.к. вызов this.setState здесь не будет приводить к дополнительной перерисовке.

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

В связи с тем, что в React Fiber (после 16 beta) эта функция может вызываться несколько раз перед функцией render, не рекомендуется выполнять здесь никакие операции вызывающие сайд-эффекты.

По умолчанию, все компоненты будут перерисовывать себя всякий раз, когда их состояние (state) изменяется, изменяется контекст или они принимают props от родителя. Если перерисовка компонента довольно тяжелая (например генерация чарта, графика) или не рекомендуется по каким-либо перфоманс причинам, то у разработчиков есть доступ к специальной функции, которая будет вызываться всякий раз при апдейт цикле.

Эта функция будет вызываться с следующими значениями props, состоянием (state) и объектом. И разработчик может использовать эти параметры для того чтобы решить нужно ли делать перерисовку компонента или вернуть false и предотвратить ее. В противном случае от вас ожидают, что вы вернете true.

Если мы не реализовали функцию shouldComponentUpdate или же решили, что компонент должен обновиться в этом рендер цикле, вызовется другая функция жизненного цикла. Эта функция в основном используется для того чтобы сделать синхронизацию между состоянием (state) и props в случае если часть состояния компонента базируется на каких-либо props.

В случаях когда shouldComponentUpdate реализована, функция componentWillUpdate может быть использована вместо componentWillReceiveProps, т.к. она будет вызываться только тогда, когда компонент действительно будет перерисован.

Подобно всем другим componentWill* функциям, эта функция может быть вызывана несколько раз перед render, поэтому не рекомендуется выполнять здесь никакие операции вызывающие сайд-эффекты.

Эта функция будет вызываться после того как отработала функция render, в каждом цикле перерисовки. Это означает, что вы можете быть уверены, что компонент и все его дочерние компоненты уже перерисовали себя.

В связи с этим эта функция является единственной функцией, что гарантировано будет вызвана только раз в каждом цикле перерисовки, поэтому любые сайд-эффекты рекомендуется выполнять именно здесь. Как componentWillUpdate и componentWillRecieveProps в эту функцию передается предыдущие props, состояние (state) и контекст, даже если в этих значениях не было изменений. Поэтому разработчики должны вручную проверять переданные значения на изменения и только потом производить различные апдейт операции.

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

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

Когда происходит какая-либо ошибка, эта функция вызывается с следующими параметрами:

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

Т.к. эта функция гарантирована будет вызвана лишь раз, то это превосходный кандидат для выполнения любых сайд-эффектов, как то AJAX запросы.

Используйте эту функцию для «очистки» после компонента, если он использует таймеры (setTimeout, setInterval), открывает сокеты или производит любые операции, которые нуждаются в закрытии или удалении.

Циклы компонента

Есть несколько причин по которым компонент может перерисовываться, и в зависимости от причины вызываются различные функции, позволяющие разработчику выполнять обновление определенных частей компонента.

Первый цикл это создание компонента, которое обычно происходит при первом обнаружении компонента в распарсенном JSX дереве:
жизненный цикл приложения react

Компонент перерисовывается в связи с перерисовкой родительского компонента

жизненный цикл приложения react

Компонент перерисовывается в связи с внутренними изменениями (например вызов this.setState())

жизненный цикл приложения react

Компонент перерисовывается в связи с вызовом this.forceUpdate

жизненный цикл приложения react

Компонент перерисовывается в связи с перехватом ошибки

Введено в React 16 как ErrorBoundaries. Компонент может определять специальный слой, который может перехватывать ошибки и предоставлять новый метод жизненного цикла – componentDidCatch – который дает разработчику возможность обработать или залогировать эти ошибки.

жизненный цикл приложения react

@James_k_nelson — недавно опубликовал componentWillRecieveProps симулятор. ТУТ вы можете найти и поиграться с этим симулятором.

React 16.3+ жизненный цикл компонента

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

static getDerivedStateFromProps(nextProps, prevState)

Основная ответственность этой новой функции — это убедиться, что состояние (state) и props синхронизированы, когда это необходимо. Ее основной смысл — это замена componentWillRecieveProps.

getDerivedStateFromProps – это статическая функция и поэтому не имеет доступа к this – вместо этого от вас ожидают, что вы вернете объект, который будет смержен в будущее состояние компонента (в точности как работа с setState!)

Эта функция используется, когда компонент обновляется, но также и когда он монтируется, сразу после вызова конструктора, поэтому вам больше не нужно использовать конструктор если вы хотите установить начальное состояние компонента из props.

Другая из двух новых функций, вызывается в так называемой “pre-commit фазе”, прямо перед изменениями из VDOM, которые должны быть отображены в DOM.

Ее можно использовать в основном, если вам нужно прочитать текущее состояние DOM.
Например у вас есть приложение, в котором новые сообщения добавляются сверху экрана – если пользователь будет скроллить вниз, и добавится новое сообщение, экран будет «прыгать» и это сделает UI тяжелее в использовании. Добавлением getSnapshotBeforeUpdate вы сможете рассчитать текущее положение скролла и восстанавливать его через апдейт DOM-а.

Хотя функция не является статической, рекомендуется возвращать значение, а не апдейтить компонент. Возвращаемое значение будет передано в componentDidUpdate как 3-й параметр.

Несмотря на то, что новые функции делают ваш переход на AsyncMode легче, вас не заставляют мигрировать весь ваш код. Следующие функции будут маркированы как устаревшие и в следующих релизах переименованы:

Dan Abramov суммировал все изменения в одной картинке:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *