Sådan bliver du professionel med React setState () på 10 minutter
Denne artikel er rettet mod folk, der allerede har haft deres første tilgang til React, og som som begyndere er i tvivl om, hvordan det setState
fungerer, og hvordan man bruger det korrekt. Det skal også hjælpe mellem- og seniorudviklere med at bruge renere og mere abstrakte måder at indstille tilstand på og få højere ordensfunktioner til at håndtere og abstrakt tilstand.
Bare læs og have det sjovt!
Så tag en kop kaffe og fortsæt med at læse! ?
Grundlæggende begreber for setState ()
React Components giver dig mulighed for at opdele brugergrænsefladen (UI) i uafhængige genanvendelige stykker, så du kan tænke på hvert stykke isoleret.
Konceptuelt er komponenter som JavaScript-funktioner. De accepterer vilkårlige input (kaldet "rekvisitter") og returnerer React-elementer, der beskriver, hvad der skal vises på skærmen.
Hvis du har brug for at give brugeren mulighed for at indtaste noget eller på en eller anden måde ændre de variabler, som komponenten modtager som rekvisitter, skal du bruge setState
.
Uanset om du erklærer en komponent som en funktion eller en klasse, må den aldrig ændre sine egne rekvisitter.
Alle reaktionskomponenterskal fungere som rene funktioner med hensyn til deres rekvisitter. Dette betyder funktioner, der aldrig prøver at ændre deres indgange og altid returnerer det samme resultat for de samme indgange.
Selvfølgelig er applikations-UI'er dynamiske og ændres over tid. Derfor state
blev oprettet.
State
giver React-komponenter mulighed for at ændre deres output over tid som reaktion på brugerhandlinger, netværkssvar og alt andet uden at krænke denne regel.
Komponenter defineret som klasser har nogle yderligere funktioner. Lokal tilstand er en funktion, der kun er tilgængelig for klassekomponenter.
setState
er den API-metode, der følger med biblioteket, så brugeren er i stand til at definere og manipulere tilstand over tid.
Tre tommelfingerregler ved brug af setState ()
Du må ikke ændre tilstand direkte

Statlige opdateringer kan være asynkrone
React kan gruppere flere setState()
opkald i en enkelt opdatering med henblik på ydeevne.
Fordi this.props
og this.state
muligvis opdateres asynkront, bør du ikke stole på deres værdier til beregning af den næste tilstand.

Du bør altid gøre denne form for manipulation med en funktionel tilgang, der leverer den state
og props
og returnere den nye state
baseret på førstnævnte.
Statlige opdateringer flettes
Når du ringer setState()
, fletter React det objekt, du giver, til det aktuelle state
.
I eksemplet nedenfor opdaterer vi variablen dogNeedsVaccination
uafhængigt af de andre state
variabler.
Fusionen er lav, så this.setState({ dogNeedsVaccination: true })
de andre variabler er intakte, og erstatter kun værdien af dogNeedsVaccination
.

Respekter datastrømmen og undgå at angive maks
Data strømmer ned! Hverken forældre eller underordnede komponenter kan vide, om en bestemt komponent er stateful eller statsløs, og de skal ikke være ligeglad med, om den er defineret som en funktion eller en klasse.
Derfor state
kaldes det ofte lokalt eller indkapslet. Det er ikke tilgængeligt for nogen anden komponent end den, der ejer og indstiller den.
Når du er setState
en prop og bruger den i din komponent, bryder du strømmen til gengivelsesrekvisitterne. Hvis den af en eller anden grund ændrede prop, der blev overført til din komponent i den overordnede komponent, gengives barnet ikke automatisk magisk igen!
Lad os kontrollere et eksempel:

Her har du en Home
komponent, der genererer et magisk nummer hver 1000 ms og sætter det til sit eget state
.
Derefter gengiver det antallet og påberåber sig tre Child
komponenter (søskende), der modtager det magiske nummer med det formål at vise det ved hjælp af tre forskellige tilgange:
Første tilgang
Komponent ChildOfHome
respekterer React-rekvisita-kaskadestrømmen, og i betragtning af at målet kun er at vise det magiske nummer, gengiver det det props
modtagne direkte.

Anden tilgang
Komponent ChildOfHomeBrother
modtager den props
fra sin forælder og componentDidMount
indstiller det magiske tal til state
. Så gengiver det state.magicNumber
.
Dette eksempel virker ikke, fordi render()
det ikke ved, at a prop
er ændret, så det ikke udløser gengivelsen af komponenten igen. Da komponenten ikke gengives længere, componentDidMount
kaldes den ikke på, og skærmen opdateres ikke.

Tredje tilgang
Normalt når vi prøver at få det til at fungere ved hjælp af den anden tilgang, tror vi noget mangler. I stedet for at tage et skridt tilbage, fortsætter vi med at tilføje ting til koden for at få det til at fungere!
Så i denne tredje tilgang har vi tilføjet for componentDidUpdate
at kontrollere, om der er en ændring for props
at udløse re-gengivelse af komponenten. Dette er unødvendigt og fører os til uren kode. Det medfører også præstationsomkostninger, der ganges med antallet af gange, vi gør dette i en stor app, hvor vi har mange lænkede komponenter og bivirkninger.
Dette er forkert, medmindre du skal tillade brugeren at ændre den modtagne propværdi.
Hvis du ikke har brug for at ændre propværdien, skal du altid prøve at holde tingene i overensstemmelse med React flow (First Approach).
Du kan tjekke en fungerende webside med dette eksempel, jeg har forberedt til dig i Glitch. Tag et kig og have det sjovt?
Tjek også koden i Home.js
og HomeCodeCleaned.js
(uden HTML-ting) i min repo om denne artikel.
Sådan indstilles stat
Så på dette tidspunkt synes jeg det er tid til at gøre vores hænder beskidte!
Lad os lege lidt med setState
og forbedre det! Bare følg med og tag endnu en kop kaffe!
Lad os oprette en lille formular til opdatering af brugerdata:

Her er koden til eksemplet ovenfor:

Vi indstiller state
som et objekt, og der er ikke noget problem, fordi vores nuværende tilstand ikke afhænger af vores sidste tilstand.
Hvad hvis vi opretter endnu et formularfelt til introduktion og visning af efternavn?


Pæn! Vi har abstraheret handleFormChange
metoden for at kunne håndtere alle inputfelter og setState
.
Hvad hvis vi tilføjer en vippeknap for at markere dataene som gyldige eller ugyldige og en tæller for at vide, hvor mange ændringer vi har foretaget i staten?


Ja! Vi gynger! Vi har abstraheret mange ting!
Hmmm ... Lad os sige, at jeg ikke vil have et afkrydsningsfelt til at styre isValid
variablen, men en simpel vippeknap.
Lad os også adskille modhåndteringen fra denne metode. Det fungerer godt, men i mere komplekse situationer, hvor React skal batch / gruppeændringer, er det ikke en god politik at stole på, at this.state.counter
variablen tilføjer en mere. Denne værdi kan ændre sig uden at du er opmærksom på det.
Vi bruger en lav kopi af det i det øjeblik, operationen påberåbes, og på det bestemte tidspunkt ved du ikke, om dens værdi er den, du forventede eller ej!
Lad os gå lidt funktionelle!


Okay - Vi har mistet abstraktion, fordi vi har adskilt håndtererne, men det er af en god grund!
Så på dette tidspunkt holder vi det handleFormChange
overførende objekt til setState
API-metoden. Men den handleCounter
og handleIsValid
metoder er nu funktionelt og starte ved at snuppe den aktuelle tilstand og derefter, afhængigt af den tilstand, ændre det til den næste.
Dette er den korrekte måde at ændre de state
variabler, der afhænger af den tidligere tilstand.
Hvad hvis vi ønsker at console.log()
angive ændringer af firstName
og lastName
inputformularer hver gang en ændring sker? Lad os prøve!

Pæn! Hver gang det handleFormChange
sker (hvilket betyder, at der skete et nyt tastetryk) logFields()
, kaldes metoden og logger den aktuelle tilstand ind i konsollen!
Lad os kontrollere browserkonsollen:

Vente! Hvad skete her folkens? Konsolloggen er en ændring før den aktuelle formularinput! Hvorfor sker dette?
setState er asynkroniseret !!
Vi vidste det allerede, men nu ser vi det med øjnene! Hvad sker der der? Lad os tage et kig på handleFormChange
og logFields
metoderne ovenfor.
Så handleFormChange
metoden modtager begivenhedsnavnet og værdien, og gør derefter en setState
af disse data. Derefter kalder det for handleCounter
at opdatere tællerinfoen og til sidst påberåber logFields
metoden. Den logFields
metode griber currentState
og returnerer 'Eduard' i stedet for 'Eduardo'.
Sagen er: setState
er asynkroniseret og handler ikke i øjeblikket. React gør sit job og udfører logFields
metoden først og forlader setState
den næste begivenhedssløjfe.
Men hvordan kan vi undgå denne slags situation?
Nå, setState
API'en callback
skal undgå denne situation:

Hvis vi ønsker, at de logFields()
skal tage højde for de nylige ændringer, vi har foretaget i staten, er vi nødt til at påberåbe det inde i tilbagekaldet, som dette:

Okay, nu fungerer det!
Vi siger til React: “Hey React! Pas på, at når du påberåber dig logFields
metoden, vil jeg have dig til at have den state
allerede opdaterede okay? Jeg stoler på dig!"
React siger: ”Okay Edo! Jeg skal håndtere alt dette parti ting, jeg normalt laver i baghaven med de setState
tingede, og først når jeg er færdig med det, vil jeg påberåbe mig logFields()
! Sej mand! Slap af!"

Og faktisk - det fungerede!
Okay alle sammen! På dette tidspunkt har vi håndteret de store faldgruber setState
.
Har du modet til at gå ud over muren? Tag en kop kaffe, og lad os virkelig kewl ...
At få lyst med setState ()
Nu hvor vi har handleCounter
og handleIsValid
metoder, og setState()
udtrykt med funktioner, kan vi komponere tilstandsopdateringen med andre funktioner! Mig kan lide komposition! Lad os have det sjovt!

Vi kan tage logikken ind setState
i en funktion uden for klassekomponenten. Lad os kalde det toggleIsValid
. ☝️

Nu kan denne funktion leve uden for klassekomponenten, hvor som helst i din app.
Hvad hvis vi bruger en højere ordensfunktion?

Wow! Nu påkalder vi ikke toggleIsValid
funktionen længere. Vi påberåber en abstrakt højere ordensfunktion kaldet toggleKey
og sender en nøgle (streng i dette tilfælde) ind i den.
Hvordan skal vi ændre toggleIsValid
funktionen nu?

Hvad?! Nu har vi en funktion kaldet toggleKey
der modtager a key
og returnerer en ny funktion som ændrer tilstand i henhold til den medfølgende nøgle.
Dette toggleKey
kan være i et bibliotek eller i en hjælperfil. Det kan påberåbes i mange forskellige sammenhænge for at ændre tilstanden for det, du ønsker, til det modsatte.
Store!
Lad os gøre det samme med forøgertællerbehandleren:


Ja! Det virker! Så sød. Lad os blive skøre nu ...
Skydning af månen og komme tilbage
Hvad hvis vi opretter en generisk makeUpdater
funktion, der modtager den transformationsfunktion, du vil anvende, tager nøglen og returnerer tilstandsfunktionen, der styrer staten med transformationsfunktionen og nøglen? Lidt forvirret? Lad os gå!

Ok, det er nok ... Lad os stoppe her. ?
Du kan kontrollere al den kode, vi har lavet i denne GitHub repo.
Sidst men ikke mindst
Glem ikke at undgå maksimal brug af tilstand og respekter React rendering rekvisitter kaskade.
Glem ikke setState
er asynkroniseret.
Glem ikke setState
kan tage et objekt eller en funktion
Glem ikke, at du skal videregive en funktion, når din næste tilstand afhænger af din tidligere tilstand.
Bibliografi
- Reager dokumentation
- Reach Tech Courses af Ryan Florence, som jeg virkelig kan anbefale.
Mange tak!