Ovaj je članak namijenjen ljudima koji su već imali prvi pristup Reactu i koji kao početnici sumnjaju u to kako setState
funkcionira i kako ga ispravno koristiti. Također bi trebao pomoći srednjim i starijim programerima da koriste čistije i apstraktnije načine postavljanja stanja i čine funkcije viših redova rukovanjem i apstraktnim stanjem.
Samo čitajte i zabavite se!
Zato uzmite šalicu kave i nastavite čitati! ?
Osnovni koncepti setState ()
React Components omogućuju vam da podijelite korisničko sučelje (UI) na neovisne dijelove koji se mogu ponovno koristiti, tako da o svakom komadu možete razmišljati izolirano.
Konceptualno, komponente su poput JavaScript funkcija. Prihvaćaju proizvoljne ulaze (nazvane "rekviziti") i vraćaju React elemente koji opisuju što bi se trebalo pojaviti na ekranu.
Ako trebate dati korisniku priliku da nešto unese ili na neki način promijeni varijable koje komponenta prima kao rekvizite, trebat će vam setState
.
Bilo da deklarirate komponentu kao funkciju ili klasu, ona nikada ne smije mijenjati vlastiti rekvizit.
Sve reakcijske komponentemoraju se ponašati kao čiste funkcije s obzirom na svoje rekvizite. To znači funkcije koje nikada ne pokušavaju promijeniti svoje ulaze i uvijek vraćaju isti rezultat za iste ulaze.
Naravno, korisnička sučelja aplikacije su dinamična i mijenjaju se tijekom vremena. Zato state
je stvoreno.
State
omogućuje React komponentama da tijekom vremena mijenjaju svoj izlaz kao odgovor na radnje korisnika, mrežne odgovore i bilo što drugo, bez kršenja ovog pravila.
Komponente definirane kao klase imaju neke dodatne značajke. Lokalno stanje je značajka dostupna samo razrednim komponentama.
setState
je API metoda koja se isporučuje s knjižnicom tako da korisnik može definirati i manipulirati stanjem tijekom vremena.
Tri pravila palca prilikom upotrebe setState ()
Nemojte izravno mijenjati državu

Ažuriranja država mogu biti asinkrona
React može grupirati više setState()
poziva u jedno ažuriranje radi izvedbe.
Zato this.props
i this.state
može se ažurirati asinkrono, da ne bi trebali oslanjati na njihove vrijednosti za izračun sljedeće stanje.

Uvijek biste trebali napraviti ovu vrstu manipulacije s funkcionalnim pristupom, stavljanje na raspolaganje state
i props
te vraća novi state
temelji se na bivše.
Ažuriranja država se spajaju
Kada nazovete setState()
, React spaja objekt koji ste unijeli u trenutni state
.
U primjeru u nastavku ažuriramo varijablu dogNeedsVaccination
neovisno o ostalim state
varijablama.
Spajanje je plitko, pa this.setState({ dogNeedsVaccination: true })
ostale varijable ostavljaju netaknutima, zamjenjujući samo vrijednost dogNeedsVaccination
.

Poštujte protok podataka i izbjegavajte navoditi maks
Podaci teku prema dolje! Ni roditeljske ni podređene komponente ne mogu znati je li određena komponenta sa statusom države ili bez nje, a ne bi ih trebalo zanimati je li definirana kao funkcija ili klasa.
Zato state
se često naziva lokalnim ili inkapsuliranim. Nije dostupan nijednoj komponenti osim one koja ga posjeduje i postavlja.
Kada setState
koristite rekvizit i koristite ga u svojoj komponenti, prekidate tok rekvizita za prikazivanje. Ako se iz nekog razloga propusnica prenesena u vašu komponentu promijeni u nadređenoj komponenti, dijete se neće automatski prikazati automatski-čarobno?!
Provjerimo primjer:

Ovdje imate Home
komponentu koja generira magični broj svakih 1000 ms i postavlja ga u svoj vlastiti state
.
Nakon toga generira broj i poziva tri Child
Komponente (braću i sestre) koje će primiti magični broj s ciljem prikazivanja pomoću tri različita pristupa:
Prvi pristup
Komponenta ChildOfHome
poštuje kaskadni tok React rekvizita i, s obzirom na to da je cilj samo prikazati magični broj, props
izravno prikazuje primljeni.

Drugi pristup
Komponenta ChildOfHomeBrother
prima props
od roditelja i, pozivajući se componentDidMount
, postavlja čarobni broj u state
. Zatim prikazuje state.magicNumber
.
Ovaj primjer ne radi jer render()
ne zna da se a prop
promijenio pa ne pokreće ponovno prikazivanje komponente. Budući da se komponenta više ne prikazuje, componentDidMount
ne poziva se i zaslon se ne ažurira.

Treći pristup
Obično kada pokušavamo učiniti da to funkcionira koristeći drugi pristup mislimo da nešto nedostaje. Umjesto da se vratimo korak unatrag, nastavljamo dodavati stvari u kôd da bi on funkcionirao!
Dakle, u ovom trećem pristupu dodali smo kako componentDidUpdate
bismo provjerili postoji li promjena u props
pokretanju ponovnog prikazivanja komponente. To je nepotrebno i vodi nas do nečistog koda. Sa sobom donosi i troškove izvedbe koji će se pomnožiti s brojem puta kada to radimo u velikoj aplikaciji u kojoj imamo puno okovanih komponenata i nuspojava.
To je pogrešno, osim ako ne trebate dopustiti korisniku da promijeni primljenu vrijednost oslonca.
Ako ne trebate mijenjati vrijednost oslonca, uvijek nastojte da stvari rade u skladu s React protokom (prvi pristup).
Možete provjeriti radnu web stranicu s ovim primjerom koji sam vam pripremio u Glitchu. Pogledajte i zabavite se?
Također pogledajte kod u Home.js
i HomeCodeCleaned.js
(bez HTML stvari) u mom izvještaju o ovom članku.
Kako postavitiState
U ovom trenutku mislim da je vrijeme da zaprljamo ruke!
Poigrajmo se malo setState
i poboljšajmo to! Samo slijedite i uzmite još jednu šalicu kave!
Stvorimo mali obrazac za ažuriranje korisničkih podataka:

Evo koda za gornji primjer:

Postavljamo state
kao objekt i nema problema jer naše trenutno stanje ne ovisi o našem posljednjem stanju.
Što ako stvorimo još jedno polje obrasca za uvođenje i prikaz prezimena?


Lijepo! Apstrahirali smo handleFormChange
metodu kako bismo mogli obrađivati sva polja za unos i setState
.
Što ako dodamo preklopni gumb za označavanje podataka kao valjanih ili nevaljanih i brojač da znamo koliko smo promjena izvršili u državi?


Da! Ljuljamo se! Saželi smo puno stvari!
Hmmm ... Recimo da ne želim potvrdni okvir za kontrolu isValid
varijable već jednostavni gumb za prebacivanje.
Odvojimo i obrađivač brojača od ove metode. Djeluje dobro, ali u složenijim situacijama kada React treba skupne / grupne promjene nije dobra politika oslanjati se na this.state.counter
varijablu da bi dodala još jednu. Ova se vrijednost može promijeniti, a da vi toga niste svjesni.
Koristimo plitku kopiju istog trenutka kada se operacija pozove i u tom određenom trenutku ne znate je li vrijednost ona koju ste očekivali ili ne!
Krenimo malo funkcionalno!


U redu - Izgubili smo apstrakciju jer smo razdvojili rukovatelje, ali to je iz dobrog razloga!
U ovom trenutku zadržavamo handleFormChange
prosljeđivanje objekta setState
API metodi. Ali metode handleCounter
and handleIsValid
sada su funkcionalne i započinju hvatanjem trenutnog stanja, a zatim ga, ovisno o tom stanju, mijenjaju u sljedeće.
Ovo je ispravan način promjene state
varijabli koje ovise o prethodnom stanju.
Što ako želimo console.log()
navesti promjene oblika firstName
i lastName
unosa svaki put kad se promjena dogodi? Pokušajmo!

Lijepo! Svaki put kada se handleFormChange
dogodi (što znači da se dogodio novi pritisak na tipku) logFields()
metoda se poziva i prijavljuje trenutno stanje u konzolu!
Provjerimo konzolu preglednika:

Čekati! Što se ovdje dogodilo? Dnevnik konzole je jedna promjena prije trenutnog unosa obrasca! Zašto se ovo događa?
setState je asinkroniziran !!
To smo već znali, ali sada to vidimo očima! Što se tamo događa? Pogledajmo gore handleFormChange
i logFields
metode.
Dakle, handleFormChange
metoda prima ime i vrijednost događaja, a zatim dobiva a setState
od ovih podataka. Zatim poziva handleCounter
da ažurira informacije o brojaču i na kraju poziva logFields
metodu. logFields
Način zgrabi currentState
i vraća „Eduard” umjesto „Eduarda”.
Stvar je u tome što je: setState
asinkroniziran i ne djeluje trenutno. React radi svoj posao i logFields
prvo izvršava metodu, ostavljajući setState
za sljedeću petlju događaja.
Ali kako možemo izbjeći ovakvu situaciju?
Pa, setState
API mora callback
izbjeći ovu situaciju:

Ako želimo logFields()
da uzme u obzir nedavne promjene koje smo napravili u državi, moramo je pozvati unutar povratnog poziva, ovako:

Dobro, sad to radi!
Kažemo Reactu: „Hej React! Imajte na umu da, kada pozivate logFields
metodu, želim da imate state
već ažuriranu, u redu? Vjerujem ti!"
React kaže: „U redu Edo! Riješit ću sve stvari koje obično radim u dvorištu sa setState
stvarčicom i tek kad završim s tim, zazvat ću logFields()
! Hladnokrvan čovjek! Opustiti!"

I zapravo - uspjelo je!
Ok svi! Do tada smo riješili glavne zamke setState
.
Imate li hrabrosti otići dalje od zida? Uzmi šalicu kave i krenimo kewl ...
Stvaranje fantazije s setState ()
Sad kad imamo handleCounter
i handleIsValid
metode, a setState()
izražene funkcijama, možemo sastaviti ažuriranje stanja s drugim funkcijama! Ja likez sastav! Idemo se zabaviti!

Logiku možemo odvesti u setState
funkciju izvan komponente klase. Nazovimo to toggleIsValid
. ☝️

Sada ova funkcija može živjeti izvan komponente klase, bilo gdje u vašoj aplikaciji.
Što ako koristimo funkciju višeg reda?

Vau! Sad više ne pozivamo toggleIsValid
funkciju. Pozivamo se na apstraktnu funkciju višeg reda koja se zove toggleKey
i u nju prosljeđujemo ključ (u ovom slučaju niz).
Kako trebamo promijeniti toggleIsValid
funkciju sada?

Što?! Sada imamo funkciju koja se naziva toggleKey
koja prima key
i vraća novu funkciju koja mijenja stanje u skladu s isporučenim ključem.
To toggleKey
može biti u knjižnici ili u pomoćnoj datoteci. Na njega se možete pozivati u puno različitih konteksta kako biste promijenili stanje bilo čega što želite u njegovu suprotnost.
Sjajno!
Učinimo isto s obrađivačem brojača priraštaja:


Da! Radi! Tako lijepo. Idemo poludjeti sada ...
Pucanje na Mjesec i povratak
Što ako stvorimo generičku makeUpdater
funkciju koja prima funkciju transformacije koju želite primijeniti, uzima ključ i vraća funkciju stanja koja upravlja stanjem s funkcijom transformacije i ključem? Malo zbunjen? Idemo!

Ok, dosta je ... Zaustavimo se ovdje. ?
Možete provjeriti sav kod koji smo napravili u ovom GitHub repo-u.
Posljednje, ali ne najmanje
Ne zaboravite izbjegavati maksimalno korištenje i poštujte kaskadno reagiranje rekvizita za prikazivanje.
Ne zaboravite da setState
je async.
Ne zaboravite da setState
možete uzeti objekt ili funkciju
Ne zaboravite da biste trebali predati funkciju kada vaše sljedeće stanje ovisi o vašem prethodnom stanju.
Bibliografija
- Reagirajte na dokumentaciju
- Dosegnite tehničke tečajeve Ryana Florencea, koje zaista preporučujem.
Hvala vam puno!