Что такое состояние в react

Использование хука состояния

Хуки — нововведение в React 16.8, которое позволяет использовать состояние и другие возможности React без написания классов.

На странице введения в хуки мы познакомились с ними на этом примере:

Давайте начнём изучать хуки, сравнив этот код с эквивалентным кодом на основе класса.

Эквивалентный пример с классом

Если вы уже пользовались классами в React, то вам знаком такой код:

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

Хуки и функциональные компоненты

Напоминаем, что функциональные компоненты в React выглядят так:

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

Хуки НЕ работают внутри классов, а используются вместо них.

Наш новый пример начинается с того, что импортирует хук useState из React:

Что такое хук? Хук — это специальная функция, которая позволяет «подцепиться» к возможностям React. Например, хук useState предоставляет функциональным компонентам доступ к состоянию React. Мы узнаем про другие хуки чуть позже.

Когда применить хук? Раньше, если вы писали функциональный компонент и осознавали, что вам нужно наделить его состоянием, вам приходилось превращать этот компонент в класс. Теперь же вы можете использовать хук внутри существующего функционального компонента. Мы покажем это прямо сейчас!

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

Объявление переменной состояния

Слово «create» («создать») было бы не совсем точно, потому что состояние создаётся только в момент, когда компонент рендерится впервые. В последующие же рендеринги useState возвращает текущее состояние. Иначе не существовало бы «состояния» как такового. Названия всех хуков начинаются с «use» тоже неспроста. О причине мы узнаем из Правил хуков.

Когда мы хотим отобразить текущее состояние счётчика в классе, мы обращаемся к this.state.count :

В функции же мы можем использовать count напрямую:

Давайте построчно пробежимся по тому, что мы выучили и проверим наши знания:

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

Совет: Что делают квадратные скобки?

Вы могли обратить внимание на квадратные скобки в месте, где объявляется переменная состояния:

Два имени в квадратных скобках не содержатся в API React. Названия переменным состояния выбираете вы:

Совет: Использование нескольких переменных состояния

Объявлять переменные состояния через пару [something, setSomething] удобно ещё и тем, что когда нам нужны несколько переменных, мы можем назвать каждую из них собственным именем:

Использовать несколько переменных состояния совсем не обязательно, потому что они могут быть объектами или массивами, которые группируют связанные по смыслу данные. Обратите внимание, что, в отличие от this.setState в классах, обновление переменной состояния всегда замещает её значение, а не осуществляет слияние.

Подробные рекомендации о разделении независимых переменных состояния вы найдёте в FAQ.

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

Источник

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

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

Рассмотрим, упомянутый ранее, пример тикающих часов.

Пока что мы знаем только один способ обновления UI.

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

Давайте начнём с инкапсуляции кода в компонент Timer :

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

Чтобы этого добиться, к компоненту Timer нужно добавить состояние.

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

Раньше состоянием могли обладать только компоненты-классы. Однако с появлением хуков состоянием могут обладать и компоненты-функции.

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

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

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

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

Давайте переместим date из props в state в три этапа.

1. Заменим this.props.value на this.state.value в методе render() :

2. Добавим конструктор класса, который устанавливает начальное состояние this.state :

Обратите внимание на то, как мы передаем свойства props в базовый конструктор:

3. Удаляем свойство value из элемента:

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

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

Далее мы сделаем так, что компонент Timer будет устанавливать таймер и обновлять себя каждую секунду.

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

При старте приложения React, компонент Timer будет впервые отрисован в DOM. В React это называется монтированием/монтажом компонента.

После каждого монтирования Timer ему нужно устанавливать таймер, чтобы периодически себя обновлять.

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

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

В документации эти методы называются «lifecycle hooks». Мы же для простоты будем называть их методами жизненного цикла (ЖЦ).

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

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

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

Когда результат отрисовки Timer вставлен в DOM, React вызывает метод componentDidMount() жизненного цикла. Внутри него компонент Timer обращается к браузеру для установки таймера, чтобы вызывать increment() раз в секунду.

Если компонент Timer в какой-то момент удалён из DOM, React вызывает метод componentWillUnmount() жизненного цикла, из-за чего таймер останавливается.

2.6.4 Корректное обновление состояния

О setState() нужно знать три вещи.

2.6.4.1 Не модифицируйте состояние напрямую

К примеру, этот компонент перерисовываться не будет:

Для корректной модификации состояния компонента используйте метод setState() :

Вы можете установить this.state только в конструкторе!

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

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

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

К примеру, такой код может не обновить температуру:

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

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

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

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

2.6.5 Нисходящий поток данных

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

Компонент может решить передать это состояние вниз как свойства props своим дочерним компонентам:

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

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

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

Каждый компонент устанавливает своё собственное значение и обновляется независимо.

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

Источник

React State с нуля

Дата публикации: 2018-04-10

Что такое состояние в react. Смотреть фото Что такое состояние в react. Смотреть картинку Что такое состояние в react. Картинка про Что такое состояние в react. Фото Что такое состояние в react

От автора: как только вы приступите к изучению React, вы столкнетесь с понятием state. State имеет огромное значение в React. Возможно, это первая причина, почему вы стали изучать React. Давайте рассмотрим понятие React state и принцип его работы.

Что такое state?

State (состояние) в React – это объект простого JS, позволяющий отслеживать данные компонента. Состояние компонента может меняться. Смена состояния компонента зависит от функциональности приложения. Изменения могут основываться на ответе от пользователя, новых сообщениях с сервера, ответа сети и т.д.

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

Компоненты класса

Состояния доступны только для компонентов класса. Главная причина, почему вы захотите использовать компоненты класса, а не функциональные компоненты заключается в том, что компоненты класса могут обладать состоянием. Давайте разберемся, в чем разница. Функциональные компоненты – это JS функции:

Что такое состояние в react. Смотреть фото Что такое состояние в react. Смотреть картинку Что такое состояние в react. Картинка про Что такое состояние в react. Фото Что такое состояние в react

Изучите основы ReactJS на практическом примере по созданию учебного веб-приложения

Источник

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

На этой странице представлена концепция состояния и жизненного цикла в компоненте 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-приложениях, имеет ли компонент состояние или нет — это внутренняя деталь реализации компонента, которая может меняться со временем. Можно использовать компоненты без состояния в компонентах с состоянием, и наоборот.

Источник

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

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