Как да станете професионалист с React setState () за 10 минути

Тази статия е насочена към хора, които вече са имали първия си подход към React и които като начинаещи се съмняват в това как setStateработи и как да го използват правилно. Той също така трябва да помогне на разработчиците от средата до старшите да използват по-чисти и по-абстрахирани начини за задаване на състояние и да накарат функциите от по-висок ред да обработват и абстрактното състояние.

Просто четете и се забавлявайте!

Затова вземете чаша кафе и продължете да четете! ?

Основни концепции на setState ()

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

Концептуално компонентите са като JavaScript функции. Те приемат произволни входове (наречени „подпори“) и връщат React елементи, описващи какво трябва да се появи на екрана.

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

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

Всички React компонентитрябва да действат като чисти функции по отношение на техния реквизит. Това означава функции, които никога не се опитват да променят своите входове и винаги връщат един и същ резултат за едни и същи входове.

Разбира се, потребителските интерфейси на приложенията са динамични и се променят с времето. Ето защо stateе създаден.

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

Компонентите, дефинирани като класове, имат някои допълнителни функции. Local state е функция, достъпна само за клас 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компонент, който генерира магическо число на всеки 1000ms и го настройва в свое собствено state.

След това той изобразява числото и извиква три Childкомпонента (братя и сестри), които ще получат магическото число с цел да го покажат, използвайки три различни подхода:

Първи подход

Компонентът ChildOfHomeзачита каскадния поток на React props и, като се има предвид, че целта е само да покаже магическото число, той рендира 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. Но handleCounterи 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.

Имате ли смелостта да преминете отвъд стената? Вземете една чаша кафе и нека да станем наистина kewl ...

Първи фантазия с setState ()

Сега, когато имаме handleCounterи handleIsValidметоди, и setState()изрази с функции, можем да композирате състояние актуализацията с други функции! Аз харесвам композиция! Хайде да се позабавляваме!

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

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

Ами ако използваме функция от по-висок ред?

Еха! Сега вече не извикваме toggleIsValidфункцията. Извикваме абстрактна функция от по-висок ред, наречена, toggleKeyи предаваме ключ (в този случай низ) в нея.

Как трябва да променим toggleIsValidфункцията сега?

Какво?! Сега имаме функция, наречена, toggleKeyкоято получава a keyи връща нова функция, която променя състоянието според предоставения ключ.

Това toggleKeyможе да бъде в библиотека или в помощен файл. Той може да бъде извикан в много различни контексти, за да промени състоянието на каквото искате в неговата противоположност.

Страхотен!

Нека направим същото с манипулатора на инкрементния брояч:

Да! Работи! Толкова хубаво. Хайде да полудеем сега ...

Снимане на Луната и връщане назад

Ами ако създадем обща makeUpdaterфункция, която получава функцията за трансформация, която искате да приложите, взема ключа и връща функцията за състояние, управляваща състоянието с функцията за трансформация и ключа? Малко объркан? Да тръгваме!

Добре, стига ... Нека спрем тук. ?

Можете да проверите целия код, който сме направили в това репо GitHub.

Последно, но не и най-малко

Не забравяйте да избягвате състоянието на максимално използване и да спазвате каскадата на React rendering props.

Не забравяйте, че setStateе асинхронно.

Не забравяйте, че setStateможете да вземете обект или функция

Не забравяйте, че трябва да предадете функция, когато следващото ви състояние зависи от предишното ви състояние.

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

  1. Документация за реагиране
  2. Достигнете до технически курсове от Райън Флорънс, които наистина препоръчвам.

Благодаря ти много!