The useState-kroken - En omfattende guide

UseState-kroken – En omfattende veiledning

Kilde node: 1780723

Hva er en stat?

Før vi dykker dypt inn i useState-kroken, la oss først forstå begrepet tilstand.

Tilstand representerer informasjon om noe på et gitt tidspunkt.

La oss for eksempel vurdere en tekstboks.

I utgangspunktet er det ingenting inne i denne tekstboksen, så tilstanden er det tom. Anta at du begynner å skrive Hallo inne i den, for hvert tastetrykk vil tilstanden til tekstboksen endres. Først vil det være "H", deretter "He", deretter "Hel" og så videre til det blir "Hei".

Legg også merke til at mens du skriver, mister du ikke den forrige verdien. Hvis du trykker "H" etterfulgt av "e" får du "He" og ikke bare "e". Med andre ord kan du tenke på staten som minne av tekstboksen.

Behovet for stat i en React-komponent.

La oss forstå dette ved hjelp av et eksempel.

Codesanbox uten stat

Her har vi en Klikkteller komponent som viser antall ganger Øk-knappen ble klikket.

Vi bruker en lokal variabel "teller" for å holde tellingen over klikkene.

Hver gang vi klikker på Øk-knappen, klikk på håndtaket funksjonen vil bli påkalt. Denne funksjonen vil øke tellerverdien med 1 og også logge verdien i konsollen.

Gå videre, klikk på Øk-knappen i CodeSandbox-forhåndsvisning.

Ingenting skjedde?

Vel, vår logikk ser ut til å være riktig. Verdien som er logget i konsollen (CodeSandbox) oppdateres riktig hver gang vi klikker, men hvorfor gjenspeiles ikke denne oppdateringen i brukergrensesnittet?

Det er på grunn av måten React fungerer på.

  • Endringer i lokale variabler utløser ikke en gjengivelse.
  • Under en re-rendering opprettes en komponent fra bunnen av, dvs. at en komponents funksjon (i dette eksemplet er det ClickCounter-funksjonen) utføres igjen. Siden variabler (for eksempel teller) er lokale for funksjonen, går deres tidligere verdier tapt.

Så hvordan får vi komponenten til å huske verdier mellom gjengivelser?

Gif kommer til et svar

Ja, du har rett! Dette gjør vi ved hjelp av useState krok.

UseState-kroken

UseState-kroken gir mekanismer for å bevare tilstanden og utløse en gjengivelse.

La oss se på bruken.

import React, { useState } from "react";
const state = useState(initialValue); // OR const state = React.useState(initialValue);

useState-kroken returnerer en matrise som inneholder to elementer:

  • A tilstandsvariabel som beholder sine verdier under gjengivelse. Startverdien som sendes til useState, tilordnes tilstandsvariabelen under den første gjengivelsen.
  • A setter funksjon som oppdaterer tilstandsvariabelen og også utløser en gjengivelse.
const state = useState(0);
const data = state[0];
const setData = state[1];

Ved hjelp av array-destrukturering , kan vi refaktorisere setningene ovenfor til en enkelt setning, som vist nedenfor:

const [data, setData] = useState(0);

Startverdien som sendes til useState, brukes bare under den første gjengivelsen. For gjengivelse ignoreres den.

Teller med useState

La oss nå oppdatere det tidligere tellereksemplet til å inkludere useState-kroken.

  • Siden vi trenger tellerverdien mellom gjengivelser, la oss konvertere den til en tilstand.
const [counter, setCounter] = useState(0);
  • Kaller setCounter inne i handleClick-funksjonen.
const handleClick = () => { setCounter(counter + 1); console.log(`%c Counter:${counter}`, "color:green");
};

SetCounter-funksjonen vil oppdatere tellerverdien med 1 og utløse en gjengivelse. Når komponentens funksjon kalles på nytt, vil tilstandsvariabelen returnert av useState ha den oppdaterte verdien.

Prøv ut CodeSandbox med den oppdaterte koden. Klikk på Øk-knappen og se magien med brukState i aksjon.

Codesanbox med useState

Du kan verifisere at den funksjonelle komponenten ved en re-rendering Klikkteller kalles opp igjen ved å se konsollloggene. Loggen "ClickCounter start" som legges til i begynnelsen av komponenten vil bli logget på hver gjengivelse.

først gjengi

gjengi

Oppdateringsfunksjon

Anta at vi ønsker å øke verdien av telleren med 4 for hvert klikk.

const handleClick = () => { setCounter(counter + 1); setCounter(counter + 1); setCounter(counter + 1); setCounter(counter + 1); console.log(`%c Counter:${counter}`, "color:green"); };

Anta at startverdien til telleren er 0. Hva forventer du å se når du klikker på knappen?

Uten oppdateringsfunksjon

Du forventet at antallet skulle være 4 ikke sant? Men hvorfor ser du 1 i stedet?

a) Hver gjengivelse er assosiert med en tilstand. Verdien av denne tilstanden forblir låst så lenge gjengivelsen varer.

Legg merke til at loggen inne i handleClick-funksjonen skriver ut tellerverdien som 0.

Uansett hvor mange ganger du kaller setCounter-metoden, forblir verdien på telleren den samme.

const handleClick = () => { setCounter(counter + 1); setCounter(counter + 1); setCounter(counter + 1); setCounter(counter + 1); console.log(`%c Counter:${counter}`, "color:green"); };
b) Inntil all koden i en hendelsesbehandler er utført, vil ikke React utløse en re-rendering.

Av denne grunn utløser ikke hvert setCounter-kall en individuell gjengivelse. I stedet legger React til disse setterfunksjonene i en kø. Utfører dem i den rekkefølgen de ble satt i kø. Oppdateringene som er gjort til staten etter å ha utført alle setningene, gjenspeiles i neste gjengivelse. Denne køen av flere tilstandsoppdateringer er kjent som batching. Det lar React være mer ytende.

Derfor får vi her en enkelt gjengivelse i stedet for 4 forskjellige gjengivelser.

Dette eksemplet er enkelt, og du kan fikse dette problemet ved å oppdatere koden som vist nedenfor:

const handleClick = () => {
setCounter(counter + 4); console.log(`%c Counter:${counter}`, "color:green"); };

Men hva om du hadde et brukstilfelle der du ønsket å oppdatere tilstanden flere ganger før neste gjengivelse.

Det er der _ updater _-funksjonen kommer til nytte.

Vi kan refaktorere det forrige eksemplet med oppdateringsfunksjonen som følger:

const handleClick = () => { setCounter(prevCounter => prevCounter + 1); setCounter(prevCounter => prevCounter + 1); setCounter(prevCounter => prevCounter + 1); setCounter(prevCounter => prevCounter + 1); console.log(`%c Counter:${counter}`, "color:green"); };

Her prevCounter ⇒ prevCounter + 1 representerer oppdateringsfunksjonen.

Som forklart tidligere, er disse oppdateringssetningene også satt i kø (batching).

Oppdateringsfunksjonen mottar en ventende/forrige tilstand som den bruker til å beregne neste tilstand.

Batching av oppdateringsfunksjon

Nedenfor er CodeSandbox med oppdateringsfunksjonen lagt til. Prøv å klikke på inkrement-knappen.

Oppdateringsfunksjon sandkasse

Initialiseringsfunksjon

Ta en titt på eksemplet nedenfor. Her kaller vi getItems-funksjonen for å få startverdien for staten.

import React from "react";
import { useState } from "react";
function ListItems() { const getItems = () => { console.log(`%c getItems called`, "color:hotpink"); return Array(50).fill(0); }; const [items, setItems] = useState(getItems()); return ( <div className="card"> <ul> {items.map((item, index) => ( <li key={index}>Item {index + 1} </li>))} </ul> <button onClick={() => setItems([...items, 0])}>Add Item</button> </div> );
} export default ListItems;

Denne funksjonen lager en matrise med størrelse 50 og fyller matrisen med nuller. Se bildet nedenfor.

Array fylt med 50 nuller

Disse elementene vises deretter på skjermen.

Alt ser ut til å være bra, men vi har et problem her.

Klikk på Legg til element knappen (plassert etter listen over elementer) for å legge til et nytt element i listen. Observer loggene.

Uten initialiseringsfunksjon

Ser du problemet her?

Loggen "getItems called" blir lagt til konsollen hver gang du legger til et element. Dette betyr at denne funksjonen blir kalt på hver gjengivelse.

Husk at useState ignorerer startverdien som sendes til den etter den første gjengivelsen, men her blir startverdien fortsatt beregnet på nytt. Dette kan være dyrt hvis vi lager store matriser eller utfører tunge beregninger.

Vi kan løse dette problemet ved å bestå getItems som en _ initialisereren _ funksjon.

La oss nå gjøre en liten endring i koden.

const [items, setItems] = useState(getItems);

Med initialiseringsfunksjon

Se konsollvinduet i CodeSandbox. Legg merke til at "getItems called"-loggen bare skrives ut på den første gjengivelsen. Når påfølgende elementer legges til, er ikke denne loggen der.

Selv om det ikke er en visuell forskjell mellom de to eksemplene, er de forskjellige når det gjelder ytelse.

Husk at når du trenger en funksjon for den opprinnelige tilstanden, må du alltid sende funksjonen eller kalle funksjonen i en annen funksjon. Ring aldri funksjonen direkte.

✅ const [items, setItems] = useState(getItems);
✅ const [items, setItems] = useState(() => getItems());
❌ const [items, setItems] = useState(getItems());

Hvor mange useState-kroker kan jeg ha

Du kan ha så mange useState-kroker inne i en komponent som den krever.

Se CodeSandbox

Multiple useState kroker

Komponenten nedenfor har tre forskjellige tilstander - brukernavn, passord, keepMeSignedIn.

Prøv å oppdatere verdiene for brukernavn, keepMeSignedIn. De oppdaterte tilstandene logges i konsollen når påloggingsknappen klikkes.

Høydepunkter

  • useState gir en mekanisme for å utløse en gjengivelse og opprettholde tilstanden mellom gjengivelsene.
  • Bruk oppdateringsfunksjonen når du trenger å:
    • Beregn neste tilstand basert på forrige tilstand.
    • Utfør flere oppdateringer av tilstanden før neste gjengivelse.
  • Hvis starttilstanden er hentet fra en funksjon – bruk initialiseringsfunksjonens syntaks.
  • Det kan være flere useState-kroker inne i en komponent.

Likte dette innlegget? Del det med andre.
Opprinnelig skrevet for min personlige blogg - https://gauravsen.com/use-state-hook

Tidstempel:

Mer fra Codementor React Fakta