Articles

Forståelse React ‘setState’

React komponenter kan, og ofte gør, Har tilstand. Tilstand kan være hvad som helst, men tænk på ting som om en bruger er logget ind eller ej og viser det korrekte brugernavn baseret på hvilken konto der er aktiv. Eller en række blogindlæg. Eller hvis en modal er åben eller ej, og hvilken fane i den er aktiv.

Reager komponenter med state render UI baseret på denne tilstand. Når tilstanden af komponenter ændres,så gør komponent UI.

det gør det vigtigt at forstå, hvornår og hvordan du ændrer tilstanden på din komponent. I slutningen af denne tutorial skal du vide, hvordan setState fungerer, og være i stand til at undgå almindelige faldgruber, som mange af os rammer, når vi lærer reagere.

arbejde med ‘setState ()’

setState() er den eneste legitime måde at opdatere tilstand efter den oprindelige tilstandsopsætning. Lad os sige, at vi har en søgekomponent og vil vise det søgeudtryk, som en bruger sender.

Her er opsætningen:

import React, { Component } from 'react'class Search extends Component { constructor(props) { super(props) state = { searchTerm: '' } }}

Vi sender en tom streng som en værdi, og for at opdatere tilstandensearchTerm, skal vi ringesetState().

setState({ searchTerm: event.target.value })

Her passerer vi et objekt tilsetState(). Objektet indeholder den del af staten, vi vil opdatere, som i dette tilfælde er værdien af searchTerm. React tager denne værdi og fusionerer den ind i det objekt, der har brug for det. Det er ligesom Search komponenten spørger, hvad den skal bruge til værdien af searchTerm og setState() reagerer med et svar.

dette starter dybest set en proces, der reagerer opkald forsoning. Afstemningsprocessen er den måde, React opdaterer DOM, ved at foretage ændringer i komponenten baseret på ændringen i tilstand. Når anmodningen til setState() udløses, opretter React et nyt træ, der indeholder de reaktive elementer i komponenten (sammen med den opdaterede tilstand). Dette træ bruges til at finde ud af, hvordan Search komponentens brugergrænseflade skal ændres som reaktion på tilstandsændringen ved at sammenligne den med elementerne i det forrige træ. React ved, hvilke ændringer der skal implementeres, og opdaterer kun dele af DOM, hvor det er nødvendigt. Derfor er React hurtig.

det lyder som meget, men for at opsummere strømmen:

  • Vi har en søgekomponent, der viser et søgeudtryk
  • det søgeudtryk er i øjeblikket tomt
  • brugeren indsender et søgeudtryk
  • dette udtryk er fanget og gemt af setState som en værdi
  • afstemning finder sted, og React bemærker ændringen i værdi
  • React instruerer søgekomponenten om at opdatere værdien, og søgeudtrykket er blevet opdateret, og søgeudtrykket er blevet fusioneret i

afstemningsprocessen ændrer ikke nødvendigvis hele træet, undtagen i en situation, hvor træets rod ændres som denne:

// old<div> <Search /></div>// new<span> <Search /></span>

alle <div>tags bliver <span> tags og hele komponenttræet opdateres som et resultat.

tommelfingerreglen er at aldrig mutere tilstand direkte. Brug altid setState() for at ændre tilstand. Ændring af tilstand direkte, ligesom uddraget nedenfor, får ikke komponenten til at gengive igen.

// do not do thisthis.state = { searchTerm: event.target.value}

passerer en funktion til `setState ()`

for at demonstrere denne ide yderligere, lad os oprette en simpel tæller, der øges og formindskes ved klik.

se pennen setState Pen af Kingsley Silas Chijioke (@kinsomicrote) på CodePen.

lad os registrere komponenten og definere markeringen for brugergrænsefladen:

class App extends React.Component {state = { count: 0 }handleIncrement = () => { this.setState({ count: this.state.count + 1 })}handleDecrement = () => { this.setState({ count: this.state.count - 1 })} render() { return ( <div> <div> {this.state.count} </div> <button onClick={this.handleIncrement}>Increment by 1</button> <button onClick={this.handleDecrement}>Decrement by 1</button> </div> ) }}

på dette tidspunkt øger tælleren simpelthen eller formindsker tællingen med 1 på hvert klik.

men hvad nu hvis vi ønskede at øge eller formindske med 3 i stedet? Vi kunne forsøge at ringe setState() tre gange i handleDecrement oghandleIncrement funktioner som dette:

handleIncrement = () => { this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 })}handleDecrement = () => { this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 })}

Hvis du koder sammen derhjemme, kan du blive overrasket over at finde ud af, at det ikke virker.

ovenstående kodestykke svarer til:

Object.assign( {}, { count: this.state.count + 1 }, { count: this.state.count + 1 }, { count: this.state.count + 1 },)

Object.assign() bruges til at kopiere data fra et kildeobjekt til et målobjekt. Hvis de data, der kopieres fra kilden til målet, alle har samme nøgler, som i vores eksempel, vinder det sidste objekt. Her er en enklere version af hvordan Object.assign() virker;

let count = 3const object = Object.assign({}, {count: count + 1}, {count: count + 2}, {count: count + 3});console.log(object);// output: Object { count: 6 }

så i stedet for opkaldet sker tre gange, sker det kun en gang. Dette kan løses ved at sende en funktion til setState(). Ligesom du sender objekter til setState(), kan du også passere funktioner, og det er vejen ud af situationen ovenfor.

Hvis vi redigererhandleIncrement – funktionen for at se sådan ud:

handleIncrement = () => { this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 }))}

…kan vi nu øge antallet tre gange med et enkelt klik.

i dette tilfælde, i stedet for at fusionere, reagerer køer funktionen opkald i den rækkefølge, de er lavet, og opdaterer hele staten det er gjort. Dette opdaterer tilstanden for optælling til 3 i stedet for 1.

få adgang til tidligere tilstand ved hjælp af Updater

når du bygger React-applikationer, er der tidspunkter, hvor du vil beregne tilstand baseret på komponentens tidligere tilstand. Du kan ikke altid stole på this.state for at holde den korrekte tilstand umiddelbart efter at have ringet setState(), da det altid er lig med den tilstand, der gengives på skærmen.

lad os gå tilbage til vores tællereksempel for at se, hvordan dette fungerer. Lad os sige, at vi har en funktion, der reducerer vores antal med 1. Denne funktion ser sådan ud:

changeCount = () => { this.setState({ count: this.state.count - 1})}

hvad vi ønsker er evnen til at formindske med 3. FunktionenchangeCount() kaldes tre gange i en funktion, der håndterer klikhændelsen som denne.

handleDecrement = () => { this.changeCount() this.changeCount() this.changeCount()}

hver gang der klikkes på knappen for at formindske, formindskes antallet med 1 i stedet for 3. Dette skyldes, at this.state.count ikke opdateres, før komponenten er blevet gengivet. Løsningen er at bruge en updater. En updater giver dig adgang til den aktuelle tilstand og bruger den straks til at opdatere andre elementer. Så changeCount() funktionen vil se sådan ud.

changeCount = () => { this.setState((prevState) => { return { count: prevState.count - 1} })}

nu er vi ikke afhængige af resultatet afthis.state. Staterne count er bygget på hinanden, så vi kan få adgang til den korrekte tilstand, der ændres med hvert opkald til changeCount().

setState() skal behandles asynkront — med andre ord, forvent ikke altid, at staten er ændret efter at have ringet setState().

indpakning

når du arbejder med setState(), dette er de vigtigste ting, du skal vide:

  • opdatering til en komponenttilstand skal udføres ved hjælp af setState()
  • du kan overføre et objekt eller en funktion til setState()
  • Pass en funktion, når du kan for at opdatere tilstand flere gange
  • afhænger ikke af dette.angiv straks efter at have ringet setState() og brug opdateringsfunktionen i stedet.