Як стати професіоналом за допомогою React setState () за 10 хвилин

Ця стаття орієнтована на людей, які вже мали перший підхід до React і які, як початківці, сумніваються в тому, як setStateпрацює і як правильно ним користуватися. Це також повинно допомогти розробникам середнього та старшого рівня використовувати більш чисті та абстраговані способи встановлення стану, а також зробити функції вищого порядку обробкою та абстрактним станом.

Просто читайте та отримуйте задоволення!

Тож візьміть чашку кави і продовжуйте читати! ?

Основні поняття setState ()

Компоненти React дозволяють розділити користувальницький інтерфейс (UI) на незалежні частини, які можна багаторазово використовувати, щоб ви могли думати про кожен фрагмент окремо.

Концептуально компоненти схожі на функції JavaScript. Вони приймають довільні входи (так звані "реквізит") і повертають елементи React, що описують, що має з'явитися на екрані.

Якщо вам потрібно надати користувачеві можливість щось ввести або якимось чином змінити змінні, які компонент отримує як реквізит, вам знадобиться setState.

Незалежно від того, декларуєте ви компонент як функцію або клас, він ніколи не повинен змінювати власні властивості.

Всі компоненти Reactповинні діяти як чисті функції щодо своїх реквізитів. Це означає функції, які ніколи не намагаються змінити свої входи і завжди повертають однаковий результат для тих самих входів.

Звичайно, інтерфейси додатків динамічні і змінюються з часом. Ось чому stateбуло створено.

State дозволяє компонентам React змінювати свої результати з часом у відповідь на дії користувача, відповіді мережі та будь-що інше, не порушуючи цього правила.

Компоненти, визначені як класи, мають деякі додаткові функції. Місцевий стан - це функція, доступна лише для класу Components.

setState - це метод API, що надається разом із бібліотекою, щоб користувач міг визначати і маніпулювати станом з часом.

Три правила великого пальця при використанні setState ()

Не змінюйте штат безпосередньо

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

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

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

Ви завжди повинні робити такого роду маніпуляцію з функціональним підходом, що постачає stateі propsта поверненням нового stateзаснованим на першому.

Оновлення штатів об’єднано

Коли ви телефонуєте setState(), React об’єднує наданий вами об’єкт із поточним state.

У наведеному нижче прикладі ми оновлюємо змінну dogNeedsVaccinationнезалежно від інших stateзмінних.

Злиття неглибоке, тому this.setState({ dogNeedsVaccination: true }) інші змінні залишаються незмінними, замінюючи лише значення dogNeedsVaccination.

Поважайте потік даних і уникайте зазначення максимальної

Дані стікають вниз! Ні батьківський, ні дочірній компоненти не можуть знати, чи є певний компонент станом чи без громадянства, і їм не повинно бути цікаво, визначений він як функція чи клас.

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

Коли ви setStateвикористовуєте проп і використовуєте його у своєму компоненті, ви порушуєте потік рендерингу реквізиту. Якщо з якихось причин властивість, передана у ваш компонент, змінилася в батьківському компоненті, дочірня особа не відтворюватиме автомагічно ?!

Давайте перевіримо приклад:

Тут у вас є Homeкомпонент, який генерує магічне число кожні 1000 мс і встановлює його як власне state.

Після цього він відтворює число і викликає три ChildКомпоненти (Брати і сестри), які отримають магічне число з метою його відображення, використовуючи три різні підходи:

Перший підхід

Компонент ChildOfHomeповажає потік каскаду реквізитів React, і, враховуючи, що мета полягає лише в тому, щоб показати магічне число, він відображає propsотримане безпосередньо.

Другий підхід

Компонент ChildOfHomeBrotherотримує propsвід свого батька і, викликаючи componentDidMount, встановлює магічне число в state. Потім він робить state.magicNumber.

Цей приклад не працює, оскільки render()не знає, що a prop змінився, тому він не ініціює повторний візуалізацію компонента. Оскільки компонент більше componentDidMountне рендерується, не викликається і дисплей не оновлюється.

Третій підхід

Зазвичай, коли ми намагаємось змусити це працювати з використанням другого підходу, ми думаємо, що чогось не вистачає. Замість того, щоб робити крок назад, ми продовжуємо додавати матеріали до коду, щоб він працював!

Отже, у цьому третьому підході ми додали, componentDidUpdateщоб перевірити, чи є зміна, propsяка ініціює повторне відображення компонента. Це непотрібно і веде нас до нечистого коду. Це також приносить із собою витрати на продуктивність, які будуть помножені на кількість разів, коли ми робимо це у великому додатку, де у нас багато ланцюжкових компонентів та побічних ефектів.

Це неправильно, якщо вам не потрібно дозволити користувачеві змінювати отримане значення опори.

Якщо вам не потрібно змінювати значення властивості, завжди намагайтеся підтримувати роботу відповідно до потоку React (перший підхід).

Ви можете перевірити робочу веб-сторінку на цьому прикладі, який я підготував для вас у Glitch. Поглянути та розважитись?

Також перевірте код у Home.jsта HomeCodeCleaned.js(без матеріалів HTML) у моєму репо про цю статтю.

Як встановити State

Тож на даний момент я думаю, що настав час забруднити руки!

Давайте трохи пограємо setStateі вдосконалимо це! Просто йдіть далі і візьміть ще одну чашку кави!

Давайте створимо невелику форму для оновлення даних користувачів:

Ось код для прикладу вище:

Ми встановлюємо stateяк об’єкт, і немає проблем, оскільки наш поточний стан не залежить від нашого останнього стану.

Що робити, якщо ми створимо ще одне поле форми для введення та відображення прізвища?

Приємно! Ми абстрагували handleFormChangeметод, щоб мати можливість обробляти всі поля введення та setState.

Що робити, якщо ми додамо кнопку перемикання, щоб позначити дані як дійсні чи недійсні, і лічильник, щоб знати, скільки змін ми внесли до стану?

Ага! Ми гойдаємось! Ми абстрагували багато речей!

Гммм ... Скажімо, я не хочу прапорець для управління isValidзмінною, а просту кнопку перемикання.

Давайте також відокремимо обробник лічильника від цього методу. Це працює добре, але в більш складних ситуаціях, коли React потребує пакетного / групового внесення змін, не дуже добре покладатися на this.state.counterзмінну, щоб додати ще одну. Це значення може змінюватися, не знаючи про це.

Ми використовуємо неглибоку його копію в той момент, коли викликається операція, і на той момент часу ви не знаєте, чи відповідає її значення такому, якого ви очікували чи ні!

Давайте трохи функціональні!

Гаразд. Ми втратили абстракцію, оскільки розділили обробників, але це з поважної причини!

Отже, зараз ми продовжуємо handleFormChangeпередавати об’єкт setStateметоду API. Але методи handleCounterand handleIsValidтепер функціональні і починаються з захоплення поточного стану, а потім, залежно від цього стану, зміни його на наступний.

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

Що робити, якщо ми хочемо console.log()констатувати зміни форм firstNameі lastNameвводу кожного разу, коли відбувається зміна? Давайте спробуємо!

Приємно! Кожного разу, коли handleFormChangeвідбувається (що означає нове натискання клавіші), logFields()метод викликається і реєструє поточний стан у консолі!

Перевіримо консоль браузера:

Чекай! Що тут сталося, люди? Журнал консолі - це одна зміна перед введенням поточної форми! Чому це відбувається?

setState є асинхронним !!

Ми це вже знали, але зараз ми бачимо це нашими очима! Що там відбувається? Давайте подивимося на handleFormChangeта logFieldsметоди вище.

Тож handleFormChangeметод отримує ім'я та значення події, а потім робить a setStateз цих даних. Потім він викликає, handleCounterщоб оновити інформацію про лічильник, і в підсумку викликає logFieldsметод. logFieldsМетод захоплює currentStateі повертає «Едуард» замість 'Едуардо.

Річ у тому, що: setStateє асинхронним і не діє в даний момент. React виконує свою роботу і logFieldsспочатку виконує метод, залишаючи setStateнаступний цикл подій.

Але як нам уникнути такої ситуації?

Ну, setStateAPI callbackповинен уникнути цієї ситуації:

Якщо ми хочемо, logFields()щоб взяти до уваги нещодавні зміни, які ми внесли в стан, нам потрібно викликати його всередині зворотного виклику, наприклад:

Гаразд, тепер це працює!

Ми говоримо React: “Гей React! Пам'ятайте, що коли ви викликаєте logFieldsметод, я хочу, щоб у вас stateуже було оновлено добре? Я довіряю тобі!"

React каже: “Добре Едо! Я збираюся впоратись із усією цією партією речей, які я зазвичай роблю на задньому дворі разом із setStateштучкою, і лише коли я закінчу з цим, я покличусь logFields()! Крутий чувак! Розслабтесь! »

І власне кажучи - це спрацювало!

Гаразд усім! На цей час ми впоралися з основними підводними каменями setState.

У вас є мужність вийти за межі стіни? Візьміть чашку кави і давайте по-справжньому ...

Знайомство з setState ()

Тепер, коли ми маємо handleCounterі handleIsValidметоди, і setState()виражені функціями, ми можемо складати оновлення стану з іншими функціями! Мені подобається композиція! Давай розважимось!

Ми можемо взяти логіку всередині setStateфункції поза компонентом класу. Назвемо це toggleIsValid. ☝️

Тепер ця функція може працювати поза компонентом класу, де завгодно у вашому додатку.

Що робити, якщо ми використовуємо функцію вищого порядку?

Оце Так! Тепер ми більше не викликаємо toggleIsValidфункцію. Ми викликаємо абстрактну функцію вищого порядку, що викликається, toggleKeyі передаємо в неї ключ (у цьому випадку рядок).

Як нам toggleIsValidзараз змінити функцію?

Що?! Тепер у нас є функція, яка називається toggleKeyта отримує keyта повертає нову функцію, яка змінює стан відповідно до поставленого ключа.

Це toggleKeyможе бути в бібліотеці або у допоміжному файлі. Це може бути використано в багатьох різних контекстах, щоб змінити стан будь-чого, що ви хочете, на його протилежність.

Чудово!

Зробимо те саме з обробником лічильника приросту:

Ага! Це працює! Так гарно. Давайте божеволіти зараз ...

Зйомка Місяця і повернення

Що робити, якщо ми створимо загальну makeUpdaterфункцію, яка отримує функцію перетворення, яку ви хочете застосувати, бере ключ і повертає функцію стану, що керує станом, за допомогою функції перетворення та ключа? Трохи розгублений? Ходімо!

Гаразд, досить ... Зупинимось тут. ?

Ви можете перевірити весь код, який ми створили в цьому репозиторії GitHub.

Останнє, але не найменше

Не забувайте уникати максимального стану використання та поважайте каскад реквізитів рендеринга React.

Не забувайте про setStateасинхронність.

Не забувайте, setStateможна взяти об'єкт або функцію

Не забувайте, що ви повинні передавати функцію, коли ваш наступний стан залежить від вашого попереднього стану.

Бібліографія

  1. Документація React
  2. Охопіть технічні курси Райана Флоренції, які я справді рекомендую.

Дуже дякую!