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 setStatefungerer, 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 stateblev 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.statemuligvis 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 stateog propsog returnere den nye statebaseret 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 dogNeedsVaccinationuafhængigt af de andre statevariabler.

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 statekaldes 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 setStateen 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 Homekomponent, 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 Childkomponenter (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 ChildOfHomerespekterer React-rekvisita-kaskadestrømmen, og i betragtning af at målet kun er at vise det magiske nummer, gengiver det det propsmodtagne direkte.

Anden tilgang

Komponent ChildOfHomeBrothermodtager den propsfra sin forælder og componentDidMountindstiller 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, componentDidMountkaldes 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 componentDidUpdateat kontrollere, om der er en ændring for propsat 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.jsog 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 setStateog 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 statesom 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 handleFormChangemetoden 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 isValidvariablen, 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.countervariablen 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 handleFormChangeoverførende objekt til setStateAPI-metoden. Men den handleCounterog handleIsValidmetoder 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 statevariabler, der afhænger af den tidligere tilstand.

Hvad hvis vi ønsker at console.log()angive ændringer af firstNameog lastNameinputformularer hver gang en ændring sker? Lad os prøve!

Pæn! Hver gang det handleFormChangesker (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å handleFormChangeog logFieldsmetoderne ovenfor.

handleFormChangemetoden modtager begivenhedsnavnet og værdien, og gør derefter en setStateaf disse data. Derefter kalder det for handleCounterat opdatere tællerinfoen og til sidst påberåber logFieldsmetoden. Den logFieldsmetode griber currentStateog returnerer 'Eduard' i stedet for 'Eduardo'.

Sagen er: setStateer asynkroniseret og handler ikke i øjeblikket. React gør sit job og udfører logFieldsmetoden først og forlader setStateden næste begivenhedssløjfe.

Men hvordan kan vi undgå denne slags situation?

Nå, setStateAPI'en callbackskal 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 logFieldsmetoden, vil jeg have dig til at have den stateallerede 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 setStatetingede, 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 handleCounterog handleIsValidmetoder, 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 setStatei 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 toggleIsValidfunktionen længere. Vi påberåber en abstrakt højere ordensfunktion kaldet toggleKeyog sender en nøgle (streng i dette tilfælde) ind i den.

Hvordan skal vi ændre toggleIsValidfunktionen nu?

Hvad?! Nu har vi en funktion kaldet toggleKeyder modtager a keyog returnerer en ny funktion som ændrer tilstand i henhold til den medfølgende nøgle.

Dette toggleKeykan 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 makeUpdaterfunktion, 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 setStateer asynkroniseret.

Glem ikke setStatekan 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

  1. Reager dokumentation
  2. Reach Tech Courses af Ryan Florence, som jeg virkelig kan anbefale.

Mange tak!