UseState hook - kattava PlatoBlockchain Data Intelligence -opas. Pystysuuntainen haku. Ai.

UseState hook – kattava opas

Mikä on valtio?

Ennen kuin sukeltaamme syvälle useState hookiin, ymmärretään ensin termi valtio.

Tila edustaa tietoa jostakin tietyllä hetkellä.

Tarkastellaan esimerkiksi tekstilaatikkoa.

Aluksi tässä tekstilaatikossa ei ole mitään, joten sen tila on tyhjä. Oletetaan, että alat kirjoittaa siihen Hello, tekstilaatikon tila muuttuu jokaisella näppäimen painalluksella. Aluksi se on "H", sitten "He", sitten "Hel" ja niin edelleen, kunnes siitä tulee "Hei".

Huomaa myös, että kun kirjoitat, et menetä aiempaa arvoa. Jos painat "H" ja "e", saat "He" eikä vain "e". Toisin sanoen voit ajatella valtiota muisti tekstilaatikosta.

Tilan tarve React-komponentissa.

Ymmärretään tämä esimerkin avulla.

Codesanbox ilman tilaa

Tässä meillä on NapsautaLaskuri komponentti, joka näyttää kuinka monta kertaa Increment-painiketta on napsautettu.

Käytämme a paikallinen muuttuja "laskuri" pitääksesi klikkausten määrän.

Joka kerta kun napsautamme Lisää-painiketta, kahvaNapsauta toiminto otetaan käyttöön. Tämä toiminto lisää laskurin arvoa yhdellä ja kirjaa arvon myös konsoliin.

Siirry eteenpäin, napsauta Lisää-painiketta CodeSandbox-esikatselussa.

Mitään ei tapahtunut?

Logiikkamme näyttää olevan oikea. Konsoliin (CodeSandbox) kirjattu arvo päivittyy oikein joka kerta, kun napsautamme, mutta miksi tämä päivitys ei näy käyttöliittymässä?

Se johtuu tavasta, jolla React toimii.

  • Muutokset paikallisiin muuttujiin eivät käynnistä uudelleenhahmonnusta.
  • Uudelleenrenderöinnin aikana komponentti luodaan tyhjästä eli komponentin toiminto (tässä esimerkissä se on ClickCounter-funktio) suoritetaan uudelleen. Koska muuttujat (esimerkiksi laskuri) ovat paikallisia funktiolle, niiden aiemmat arvot menetetään.

Joten miten saamme komponentin muistamaan arvot renderöintien välillä?

Kyllä, ymmärsit oikein! Teemme tämän avulla useState koukku.

UseState-koukku

UseState-koukku tarjoaa mekanismeja tilan säilyttämiseksi ja uudelleenrenderöinnin käynnistämiseksi.

Katsotaanpa sen käyttöä.

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

// OR

const state = React.useState(initialValue);

UseState-koukku palauttaa taulukon, joka sisältää kaksi kohdetta:

  • A tilamuuttuja joka säilyttää arvonsa uudelleenrenderöinnin aikana. UseStatelle välitetty alkuarvo määritetään tilamuuttujalle ensimmäisen renderöinnin aikana.
  • A asetintoiminto joka päivittää tilamuuttujan ja laukaisee myös uudelleen renderöinnin.
const state = useState(0);
const data = state[0];
const setData = state[1];

Käyttäminen taulukon rakenteen purkaminen , voimme muuntaa yllä olevat lauseet yhdeksi lauseeksi alla esitetyllä tavalla:

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

UseStatelle välitettyä alkuarvoa käytetään vain ensimmäisen renderöinnin aikana. Uudelleenrenderöinnissä se jätetään huomiotta.

Laskuri useStaten kanssa

Päivitetään nyt aiempi laskuriesimerkki sisältämään useState-koukku.

  • Koska tarvitsemme laskurin arvon uusintahahmonnusten välillä, muunnetaan se tilaan.
const [counter, setCounter] = useState(0);
  • SetCounterin kutsuminen handleClick-toiminnon sisällä.
const handleClick = () => {
  setCounter(counter + 1);
  console.log(`%c Counter:${counter}`, "color:green");
};

SetCounter-toiminto päivittää laskurin arvon yhdellä ja käynnistää uudelleenrenderöinnin. Kun komponentin toimintoa kutsutaan uudelleenrenderöinnissa, useStaten palauttamalla tilamuuttujalla on päivitetty arvo.

Kokeile CodeSandboxia päivitetyllä koodilla. Napsauta Increment-painiketta ja näe useStaten taika toiminnassa.

Codesanbox useStaten kanssa

Voit varmistaa sen uudelleenrenderöimällä, toiminnallinen komponentti NapsautaLaskuri kutsutaan uudelleen tarkastelemalla konsolin lokeja. Loki “ClickCounter start”, joka lisätään komponentin alkuun, kirjataan jokaiseen renderöintiin.

ensimmäinen render

renderöi uudelleen

Päivitystoiminto

Oletetaan, että haluamme kasvattaa laskurin arvoa 4:llä jokaisella napsautuksella.

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

Oletetaan, että laskurin alkuarvo on 0. Mitä odotat näkeväsi, kun painiketta napsautetaan?

Ilman päivitystoimintoa

Odotitko luvun olevan 4? Mutta miksi näet sen sijaan 1?

a) Jokainen renderöinti liittyy tilaan. Tämän tilan arvo pysyy lukittuna koko renderöinnin ajan.

Huomaa, että handleClick-funktion sisällä oleva loki tulostaa laskurin arvon 0.

Riippumatta siitä, kuinka monta kertaa kutsut setCounter-menetelmää, laskurin arvo pysyy samana.

const handleClick = () => {
  setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };
b) Ennen kuin kaikki tapahtumakäsittelijän sisällä oleva koodi on suoritettu, React ei käynnistä uudelleenrenderöintiä.

Tästä syystä jokainen setCounter-kutsu ei käynnistä yksittäistä hahmonnusta. Sen sijaan React lisää nämä setter-funktiot jonoon. Suorittaa ne siinä järjestyksessä, jossa ne olivat jonossa. Kaikkien lausekkeiden suorittamisen jälkeen tilaan tehdyt päivitykset näkyvät seuraavassa renderöinnissa. Tämä useiden tilapäivitysten jonottaminen tunnetaan nimellä annostelu-. Sen avulla React voi olla tehokkaampi.

Siksi tässä saamme yhden renderoinnin neljän eri renderöinnin sijaan.

Tämä esimerkki on yksinkertainen, ja voit korjata tämän ongelman päivittämällä koodin alla kuvatulla tavalla:

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

Mutta entä jos sinulla olisi käyttötapaus, jossa haluat päivittää tilan useita kertoja ennen seuraavaa renderöintiä.

Siellä _ päivittäjä _-toiminto on kätevä.

Voimme refaktoroida edellisen esimerkin päivitystoiminnolla seuraavasti:

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");
    };

Tässä prevCounter ⇒ prevCounter + 1 edustaa päivitystoimintoa.

Kuten aiemmin selitettiin, nämä päivityskäskyt ovat myös jonossa (erä).

Päivitystoiminto vastaanottaa odottavan/edellisen tilan, jota se käyttää seuraavan tilan laskemiseen.

Päivitystoimintojen erät

Alla on CodeSandbox, johon on lisätty päivitystoiminto. Kokeile klikata lisäyspainiketta.

Päivitystoiminto hiekkalaatikko

Alustustoiminto

Katso alla olevaa esimerkkiä. Tässä kutsumme getItems-funktiota saadaksemme tilan alkuarvon.

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;

Tämä funktio luo taulukon, jonka koko on 50, ja täyttää taulukon nollilla. Katso alla olevaa kuvaa.

Taulukko täytetty 50 nollalla

Nämä kohteet näkyvät sitten näytöllä.

Kaikki näyttää olevan hyvin, mutta meillä on tässä ongelma.

Klikkaa Lisää tavara -painiketta (sijaitsee kohdeluettelon jälkeen) lisätäksesi uuden kohteen luetteloon. Tarkkaile lokeja.

Ilman alustustoimintoa

Näetkö ongelman tässä?

Loki "getItems kutsutaan" lisätään konsoliin aina, kun lisäät kohteen. Tämä tarkoittaa, että tätä toimintoa kutsutaan jokaisessa renderöinnissa.

Muista, että useState jättää huomioimatta sille ensimmäisen renderöinnin jälkeen välitetyn arvon, mutta tässä alkuarvoa lasketaan edelleen uudelleen. Tämä voi olla kallista, jos luomme suuria taulukoita tai suoritamme raskaita laskelmia.

Voimme ratkaista tämän ongelman ohittamalla getItems kuin _ alustus _-funktio.

Tehdään nyt pieni muutos koodiin.

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

Alustustoiminnolla

Katso CodeSandboxin konsoliikkuna. Huomaa, että "getItems kutsutaan" -loki tulostetaan vain ensimmäisellä renderöinnillä. Kun myöhempiä kohteita lisätään, tämä loki ei ole siellä.

Vaikka näiden kahden esimerkin välillä ei ole visuaalista eroa, suorituskyvyn suhteen ne ovat erilaisia.

Muista, kun tarvitset funktion alkutilaan, välitä funktio aina tai kutsu funktiota toisen funktion sisällä. Älä koskaan kutsu toimintoa suoraan.

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

Kuinka monta useState-koukkua minulla voi olla

Komponentin sisällä voi olla niin monta useState-koukkua kuin se vaatii.

Katso CodeSandbox

Useita käyttövaltiokoukkuja

Alla olevalla komponentilla on kolme eri tilaa – käyttäjätunnus, salasana, keepMeSignedIn.

Yritä päivittää käyttäjänimen keepMeSignedIn arvot. Päivitetyt tilat kirjataan sisään konsoliin, kun kirjautumispainiketta napsautetaan.

Poimintoja

  • useState tarjoaa mekanismin uudelleenrenderöinnin käynnistämiseksi ja tilan säilyttämiseksi uudelleenrenderöinnin välillä.
  • Käytä päivitystoimintoa, kun tarvitset:
    • Laske seuraava tila edellisen tilan perusteella.
    • Tee useita päivityksiä tilaan ennen seuraavaa renderöintiä.
  • Jos alkutila saadaan funktiosta – käytä alustusfunktion syntaksia.
  • Komponentin sisällä voi olla useita useState-koukkuja.

Piditkö tästä postauksesta? Jaa se muiden kanssa.
Alunperin kirjoitettu henkilökohtaista blogiani varten - https://gauravsen.com/use-state-hook

Aikaleima:

Lisää aiheesta Codementor React Fact