История состояний React.
Состояние тяжело поддерживать. Сложнее поддерживать пользовательский интерфейс. И почти невозможно сделать пользователя счастливым.
Независимо от того, насколько хорошо вы планируете, распад всегда происходит.
React - это хорошо известная библиотека веб-интерфейса с долгой историей реализации состояний. Компоненты формируют приложение. Но задача состояния - держать его в пределах разумного.
Если только это не сводит разработчика с ума до достижения этой цели!
Разные сезоны, разные состояния.
Мы знаем, как проходят времена года. Весной распускаются цветы. Летом по подмышкам стекает пот. Осенью листья падают с веток. А кто забудет снежные зимние дни? (Подсказка: дебют людей, живущих после глобального потепления!)
Природа может напоминать большую React Component
. Часть жизни на Земле. Но она проходит через различные фазы. Мы знаем каждый из них как сезон.
Различные части интерфейсного приложения также могут находиться на разных этапах. Они являются результатом изменений в том, что мы называем state
.
Введение в наше исследование.
Представьте себе человека с плохим характером. Он ругается жарким летом. И бьет людей, когда становится достаточно холодно. Никто не может его предсказать.
Можно сказать, что на него влияет погода.
Например, весной он добрый человек, а во время дождя даже стихи поет. Зимы холодные и вызывают у него радражительность. Вот почему он предпочтет заключать сделки действием, а не переговорами.
Такому человеку не хватает хорошего управления состоянием, что делает его неспособным контролировать свое поведение. Аналогичная проблема может существовать и во интерфейсном приложении. Вот когда он дает неуместные ответы или вообще не дает.
Затем давайте кратко рассмотрим, что такое состояние в компоненте React.
Состояние компонентов React.
Состояние похоже на свойства, но является частным и полностью контролируется компонентом.
Props
сами по себе являются Objects
. Их keys
это имена attributes
которые мы передаем компоненту через JSX
. И их values
соответствуют значениям соответствующих атрибутов.
В то время как состояние может быть атрибутом или их коллекцией, оно может быть Object
, String
или любым другим JavaScript Type. Но в чем главное различие между состоянием и prop
?
Ответ: component
получает props
от своего родителя, в то время как он создает и controls
свое собственное state
.
В чем проблема?
Здесь мы можем задать вопрос: что делает приложение отличным?
Возможно преданность делу до конца. Желание доставить удовлетворение. Ощущение полезности. То, что мы можем назвать уверенностью.
Эти вещи не подталкивают плохое приложение. Оно уже чувствует себя довольным и уверенным. Его направляют на более солидные вещи. На это влияют потоки данных. По мощной инерции.
Оно не заботится об ожиданиях пользователей. И оно редко подходит для разных пользовательских историй. Работает, только если все в порядке. Что редко бывает в реальных приложениях.
Можем ли мы создать состояние, используя простую переменную?
Допустим, у нас есть компонент с именем Nature
. Этот компонент имеет основное переменное состояние: season
. Сначала давайте объявим это с помощью простого JavaScript variable
:
function Nature(props) {
let season = 'spring';
return(
<p>Currently it is {season}</p>
)
}
В строке const season = 'spring';
мы объявили нашу переменную состояния. Выходной HTML-код выглядит так:
<p>Currently it is spring</p>
Давайте добавим кнопку в возврат нашей функции. Мы передаем его событию обратный вызов onClick
, который попытается изменить значение переменной season
на «summer»:
function Nature(props) {
let season = 'spring';
const changeSeason = () => {
season = 'summer'
}
return(
<div>
<p>Currently it is {season}</p>
<button onClick={changeSeason}>Click to change season!</button>
</div>
)
}
Он выведет предыдущий результат с добавленной кнопкой. Тем не менее, если вы нажмете на кнопку, название сезона в выводе не изменится.
Значение переменной меняется на summer, но onClick
никогда не приведет к изменению выходных данных.
Почему?
Чтобы ответить на этот вопрос, мы должны узнать о React Hooks Flow
. Здесь все становится интересно.
Истории безумия компонентов.
События. Их последовательность формирует то, что мы можем назвать сюжетной линией. Например, вы могли только что закончить среднюю школу. Это важное событие для вас, которое также характеризует ваш уровень образования.
Наши воспоминания и личности состоят из событий. В наших резюме они полностью удовлетворены. И чтобы наша жизнь продолжалась, мы ожидаем и будущих событий.
Жизненный цикл компонента полон событий. Мы собираемся взглянуть на пример.
Предположим, что кнопка отправки используется для регистрации информации о пользователе. Кнопка неактивна, пока пользователь правильно не заполнит обязательные поля. Компонент формы использует переменную состояния для включения кнопки.
Работает отлично. Пользователь заполняет форму. Серая кнопка становится синей, и пользователь нажимает на нее. В фоновом режиме отправляется запрос API на регистрацию. Но пользователь не проинформирован. Они не видят никаких элементов загрузки или сообщений.
Они думают, что это не сработало, и снова нажимают на нее. И угадай что! Другой запрос отправляется в фоновом режиме. Первый запрос на регистрацию пользователя выполнен успешно.
Компонент предназначен для перенаправления пользователя в случае успеха. Но...
Ответ на второй запрос приходит в спешке. Подтверждение компонента, что электронная почта пользователя является дубликатом. Теперь другая переменная состояния, содержащая ошибку дублирования электронной почты, становится истинной.
Компонент выдает пользователю сообщение об ошибке, информирующее о том, что электронное письмо является дублированием, и перенаправление просто не работает, потому что состояние ошибки не является ложным. Компонент получил указание не перенаправлять, если состояние ошибки неясно. Что не имеет значения. И это плохое управлением состоянием.
В этом примере мы столкнулись с несколькими событиями. Один из них происходит при заполнении формы. Другой происходит, когда пользователь нажимает кнопку. Последнее событие - когда пришел ответ.
Мы, как пользователи и разработчики, можем понять эти события. Но UI-библиотека, такая как React, не так умна, как человек. Он должна быть проинструктирована о событиях и регистрировать их заранее.
Это то, что мы называем Components Hook Flow
.
Компоненты React Hook Flow
Хуки были добавлены в React с версии 16.8. В то время они были крупным обновлением, поскольку они наделили компоненты функций без сохранения состояния возможностями, которые были доступны только в компонентах класса.
Было хорошо иметь возможность запускать эффекты и изменять состояния в функциональном компоненте. Но компонент класса также предоставил разработчикам методы жизненного цикла, например componentDidMount или shouldComponentUpdate.
Функциональные компоненты и хуки не предоставляют нам методы жизненного цикла. Вместо этого разные хуки в функциональном компоненте запускаются в определенном порядке, чтобы разработчик мог реализовать одну и ту же логику жизненного цикла, учитывая этот порядок.
Hooks Flow состоит из 3 основных этапов: Mount
, Update
and Unmount
.
Когда компонент монтируется впервые, устанавливаются его начальные значения. К ним относятся функции инициализатора useState
и useReducer
. Затем он продолжит выполнение остальных кодов, которые вы добавили в свой функциональный компонент, до тех пор, пока не достигнет возвращенного значения.
Затем перед рендерингом возвращенного JSX он запустит ваш layoutEffects
, созданный с помощью хука useLayoutEffect
. Затем браузер рисует экран, чтобы отобразить React Virtual DOM. Затем вызываются effects
, которые вы зарегистрировали с помощью useEffect
.
Это простой процесс для установки компонента. Но тогда компонент нужно будет обновить. Это может произойти по двум причинам: либо изменились свойства, либо состояние было обновлено.
Этап обновления имеет свои собственные шаги: он запускает ваш функциональный компонент и обновляет DOM на основе новых изменений, возникающих в результате обновленного состояния.
На следующем шаге он очистит предыдущие эффекты layoutEffects, после чего запустит layoutEffects. Браузер перерисовывает экран, чтобы отразить изменения.
И, наконец, перед запуском эффектов react удалит предыдущие эффекты.
Этап обновления имеет тот же порядок шагов, что и этап монтажа. Отличается только деталями. Например, на этапе монтирования используются значения начального состояния, а на этапе обновления используются новые. На этапе монтирования запускаются эффекты, но сначала выполняется попытка устранить эффекты, вызванные предыдущими этапами обновления или монтирования компонента.
Третий этап в этом потоке, как мы уже упоминали, - это этап размонтирования. На этом этапе весь компонент будет удален с экрана. Так что ничего не произойдет, за исключением того, что React попытается очистить все оставшиеся эффекты и эффекты макета.
Теперь, когда мы знаем, как работает React Hooks Flow, мы можем понять, почему сохранение состояния нашего компонента внутри простой переменной не приведет к изменению DOM.
Потому что React не будет обновлять DOM, если не уверен, что что-то изменилось.
Способ, которым React прослушивает изменения состояния, похож на то, как мы можем добавить eventListeners в JS. Например, предположим, что это элемент ввода текста. Мы можем добавить слушателей для его value change
, или когда есть вход blurred
.
React добавляет слушателей к изменениям переменных состояния. И когда мы вызываем функции stateSetter, это событие запускается, и тогда React знает, как обновить DOM.
Затем давайте перепишем наш предыдущий код, чтобы он заработал.
Правильный способ объявить состояние
React предоставляет нам хук useState
для приведения состояний к функциональным компонентам. Чтобы инициализировать состояние, вам нужно вызвать хук и передать ему состояние initial value
.
Хук вернет массив из двух элементов. Первый элемент в массиве - это, state's value
, второй элемент - это state-setter function
.
Мы будем использовать эту функцию, чтобы добавить состояние сезона к нашему компоненту. Мы также перепишем нашу функцию changeSeason
, чтобы использовать функцию state-setter
, возвращаемую useState
.
function Nature(props) {
let [season, setSeason] = useState('spring');
const changeSeason = () => {
setSeason('summer')
}
return(
<div>
<p>Currently it is {season}</p>
<button onClick={changeSeason}>Click to change season!</button>
</div>
)
}
Теперь после рендеринга этого компонента, если мы попытаемся нажать на кнопку, мы увидим, что название сезона в абзаце изменится на summer
.
В приведенном выше коде переменная season
относится к первому элементу, возвращаемому useState, который содержит последнее значение состояния. А setSeason - это метод, который мы можем использовать для обновления значения состояния.
Мы узнали, как мы можем привести состояния к функциональному компоненту в React. И мы также узнали, как работают состояния в более фундаментальном смысле.
Зная, как правильно объявить состояние, возникает отличный вопрос: есть ли еще правильный способ использовать состояния в React?
Жизнь - это путешествие (как и разработка на React)
Никто не похож на других. Никто не разделяет те же интересы, что и другие. Мы все уникальны своими предпочтениями. И эта уникальность также влияет на то, как мы живем.
У разных проектов React тоже есть свои отличия. Они различаются тем, как они управляют своими состояниями, эффектами, деревьями компонентов или даже структурами папок.
Никто не заявляет, что вы должны структурировать проект React определенным образом. Вы должны понимать базовый образ мышления, который React использует для управления повторными рендерингами, реквизитами, состояниями, эффектами и т. д.
В этой статье мы узнали о том, как React реализует состояния. Надеюсь, это поможет вам лучше понять, что это такое и почему они важны.
Это уже длинная статья, и я закончу ее здесь, так как не хочу утомлять вас дополнительной информацией. Но позвольте мне добавить еще один совет. Каждый раз, когда вы сомневались, следует ли вам использовать состояние или нет, попробуйте ответить на этот вопрос: должны ли изменения в переменной вызывать повторный рендеринг?