Förståelse Reagera `setState`

0
44

Reagera komponenter kan, och ofta gör det, har staten. Staten kan vara vad som helst, men tänk på saker som om en användare är inloggad eller inte och visa rätt användarnamn baserat på vilket konto är aktivt. Eller en samling av blogginlägg. Eller om en modal är öppen eller inte och vilken flik som inom den är aktiv.

Reagera komponenter med staten göra ANVÄNDARGRÄNSSNITT baserat på den staten. När staten av komponenter förändringar, så är den del UI.

Som gör att förstå när och hur för att ändra status för din komponent viktigt. I slutet av denna tutorial, du ska veta hur setState fungerar, och kunna undvika vanliga fallgropar som många av oss drabbades när när man lär sig att Reagera.

Arbetet i `setState()`

setState() är den enda legitima sättet att uppdatera staten efter det ursprungliga tillståndet setup. Låt säga att vi har en sökning komponent och vill visa söktermen en användare skickar.

Här är setup:

importera Reagera, { Komponent } ‘reagerar’

klass Sök sträcker Komponent {
konstruktör(rekvisita) {
super(rekvisita)

state = {
searchTerm:”
}
}
}

Vi passerar en tom sträng som värde och, för att uppdatera status för searchTerm, vi måste ringa setState().

setState({ searchTerm: händelse.- målet.värde })

Här ska vi passerar ett objekt för att setState(). Objektet innehåller en del av det tillstånd vi vill uppdatera, som i detta fall, är värdet av searchTerm. Reagera tar detta värde och sammanfogar det till det objekt som behöver det. Det är ungefär som att Söka komponent frågar vad det ska användas för värdet av searchTerm och setState() svarar med ett svar.

Detta är i grund och botten att sparka igång en process som Reagerar samtal försoning. Försoning är det sätt att Reagera uppdateringar DOM, genom att göra ändringar till den del baserad på förändringen i staten. När en begäran om att setState() aktiveras, Reagerar skapar ett nytt träd som innehåller reaktiva element i den del som (tillsammans med den uppdaterade staten). Detta träd som används för att räkna ut hur Sökningen komponent UI bör förändras till följd av att staten förändring genom att jämföra det med de delar av den tidigare träd. Reagera vet vilka ändringar för att genomföra och endast kommer att uppdatera delar av DOM vid behov. Detta är anledningen till att Reagera snabbt.

Det låter som mycket, men för att sammanfatta flöde:

  • Vi har en sök-komponenten som visar en sökterm
  • Att söktermen är för närvarande tom
  • Användaren skickar en sökterm
  • Detta begrepp fångas in och lagras av setState som ett värde
  • Avstämningen sker och Reagera märker förändringen i värdet
  • Reagera instruerar sök komponent för att uppdatera värdet och söktermen är sammanslagna i

Försoningsprocessen inte nödvändigtvis att förändra hela trädet, utom i en situation där roten av trädet ändras så här:

// gammal
<div>
<Search />
</div>

// nya
<span>
<Search />
</span>

Alla <div> – taggar bli <span> – taggar och hela komponenten träd kommer att uppdateras som följd.

Den tumregel är att aldrig mutera staten direkt. Använd alltid setState() för att ändra läge. Ändring av staten direkt, som utdraget nedan kommer inte att orsaka komponent för att åter göra.

// inte gör detta
detta.state = {
searchTerm: händelse.- målet.värde
}

Passerar en Funktion för att `setState()`

För att visa denna idé ytterligare, låt oss skapa en enkel räknare som ökningar och minskningar på klicka.

Se Pennan setState Penna av Kingsley Silas Chijioke (@kinsomicrote) på CodePen.

Låt oss registrera komponent och definiera märkord för UI:

klass App sträcker sig Reagera.Komponent {

state = { count: 0 }

handleIncrement = () => {
detta.setState({ count: här.stat.count + 1 })
}

handleDecrement = () => {
detta.setState({ count: här.stat.count – 1 })
}
render() {
avkastning (
<div>
<div>
{detta.stat.count}
</div>
<button onClick={detta.handleIncrement}>ökas med 1</button>
<button onClick={detta.handleDecrement}>Minska med 1</button>
</div>
)
}
}

Vid denna punkt, disk helt enkelt ökningar eller minskningar räkna med 1 på varje klick.

Men vad händer om vi ville öka eller minska med 3 istället? Vi kan prova att ringa setState() tre gånger i handleDecrement och handleIncrement funktioner så här:

handleIncrement = () => {
detta.setState({ count: här.stat.count + 1 })
detta.setState({ count: här.stat.count + 1 })
detta.setState({ count: här.stat.count + 1 })
}

handleDecrement = () => {
detta.setState({ count: här.stat.count – 1 })
detta.setState({ count: här.stat.count – 1 })
detta.setState({ count: här.stat.count – 1 })
}

Om du är kodning tillsammans hemma, du kanske blir förvånad över att hitta som inte fungerar.

Ovanstående kod utdrag motsvarar:

Objektet.tilldela(
{},
{ count: här.stat.count + 1 },
{ count: här.stat.count + 1 },
{ count: här.stat.count + 1 },
)

Objektet.tilldela() används för att kopiera data från en källa objekt till ett objekt. Om den data som kopieras från källan till målet alla har samma nycklar, som i vårt exempel, att det sista objektet som vinner. Här är en enklare version av hur Objekt.tilldela() verk.

låt count = 3

const objekt = Objekt.tilldela({},
{count: count + 1},
{count: count + 2},
{count: count + 3}
);

konsolen.log(objekt);
// output: Object { count: 6 }

Så istället för den kalla händer tre gånger, det händer bara en gång. Detta kan fixas genom att skicka en funktion för att setState(). Precis som du skicka objekt till setState(), du kan också gå funktioner, och det är det som är vägen ut ur situationen ovan.

Om vi redigerar handleIncrement funktion för att se ut så här:

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

…vi kan nu öka räknas tre gånger med ett klick.

I det här fallet, istället för att sammanfoga, Reagera köer funktionen samtal i den ordning de är gjorda och uppdateringar hela staten sådana att det är gjort. Detta uppdateringar staten räkna till 3 istället för 1.

Tillgång Föregående Staten Använder Updater

När man bygger Reagera program, det finns tillfällen när du vill beräkna stat som bygger komponenten tidigare tillstånd. Du kan inte alltid lita på detta.tillstånd att hålla rätt tillstånd omedelbart efter kalla setState(), så det är alltid lika staten återges på skärmen.

Låt oss gå tillbaka till våra counter-exempel för att se hur detta fungerar. Låt säga att vi har en funktion som sänker våra räkna med 1. Denna funktion ser ut så här:

changeCount = () => {
detta.setState({ count: här.stat.count – 1})
}

Vad vi vill ha är möjligheten att minska med 3. Det changeCount() funktionen anropas tre gånger i en funktion som hanterar klicka på evenemang.

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

Varje gång knappen för att minska klickat på den räkningen kommer att minska med 1 istället för 3. Detta är på grund av detta.stat.räkna inte uppdateras förrän komponent har varit re-renderade. Lösningen är att använda en updater. En updater kan du få tillgång till aktuella läget och sätta den i bruk omedelbart för att uppdatera andra objekt. Så changeCount () – funktionen kommer att se ut så här.

changeCount = () => {
detta.setState((prevState) => {
return { count: prevState.räkna med 1}
})
}

Nu är vi inte beroende på resultatet av detta.stat. De stater som räknas är byggda på varandra så vi har tillgång till rätt tillstånd som förändringar med varje samtal för att changeCount().

setState() bör behandlas asynkront — med andra ord, inte alltid räkna med att staten har förändrats efter ringer setState().

Att Linda Upp

När du arbetar med setState(), dessa är de viktiga saker du bör veta:

  • Uppdatera till en komponent staten bör göras med hjälp av setState()
  • Du kan skicka ett objekt eller en funktion för att setState()
  • Gå till en funktion när du kan uppdatera staten flera gånger
  • Inte bero på detta.tillstånd omedelbart efter kalla setState() och använda sig av updater funktion istället.