Cârligul useState - Un ghid cuprinzător PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Cârligul useState – Un ghid cuprinzător

Ce este un stat?

Înainte de a ne aprofunda în cârligul useState, să înțelegem mai întâi termenul de stat.

Starea reprezintă informații despre ceva la un moment dat în timp.

De exemplu, să luăm în considerare o casetă de text.

Inițial, nu există nimic în interiorul acestei casete de text, deci starea sa este gol. Să presupunem că începeți să tastați Hello în interiorul acestuia, pentru fiecare apăsare de tastă starea casetei de text se va schimba. La început va fi „H”, apoi „El”, apoi „Hel” și așa mai departe până devine „Hello”.

De asemenea, observați că, pe măsură ce introduceți, nu pierdeți valoarea anterioară. Dacă apăsați „H” urmat de „e”, primiți „El” și nu doar „e”. Cu alte cuvinte, te poți gândi la stat ca fiind memorie a casetei de text.

Nevoia de stare într-o componentă React.

Să înțelegem asta cu ajutorul unui exemplu.

Codesanbox fara stat

Aici avem un ClickCounter componentă care afișează de câte ori a fost apăsat butonul Incrementare.

Folosim un variabila locala „contor” pentru a ține contorizarea clicurilor.

De fiecare dată când facem clic pe butonul Incrementare, mâner Faceți clic va fi invocată funcția. Această funcție va crește valoarea contorului cu 1 și, de asemenea, va înregistra valoarea în consolă.

Continuați, faceți clic pe butonul Incrementare din previzualizarea CodeSandbox.

Nu s-a intamplat nimic?

Ei bine, logica noastră pare a fi corectă. Valoarea înregistrată în consolă (CodeSandbox) se actualizează corect de fiecare dată când facem clic, dar de ce nu se reflectă această actualizare în UI?

Este din cauza modului în care funcționează React.

  • Modificările la variabilele locale nu declanșează o redare.
  • În timpul unei re-rendari, o componentă este creată de la zero, adică funcția unei componente (în acest exemplu este funcția ClickCounter) este executată din nou. Deoarece variabilele (de exemplu, contorul) sunt locale pentru funcție, valorile lor anterioare se pierd.

Deci, cum facem ca componenta să-și amintească valorile dintre randări?

Da, ai inteles bine! Facem asta cu ajutorul useState cârlig.

Cârligul useState

Cârligul useState oferă mecanisme pentru a păstra starea și a declanșa o re-rendare.

Să ne uităm la utilizarea sa.

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

// OR

const state = React.useState(initialValue);

Hook-ul useState returnează o matrice care conține două elemente:

  • A variabilă de stare care își păstrează valorile în timpul redărilor. Valoarea inițială transmisă la useState este atribuită variabilei de stare în timpul primei randări.
  • A funcția setter care actualizează variabila de stare și, de asemenea, declanșează o re-rendare.
const state = useState(0);
const data = state[0];
const setData = state[1];

Utilizarea destructurarea matricei , putem refactoriza declarațiile de mai sus într-o singură declarație, așa cum se arată mai jos:

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

Valoarea inițială transmisă la useState este utilizată numai în timpul primei randări. Pentru redări, este ignorată.

Contor cu useState

Acum, să actualizăm exemplul de contor anterior pentru a include cârligul useState.

  • Deoarece avem nevoie de contravaloarea dintre re-rendări, să o transformăm într-o stare.
const [counter, setCounter] = useState(0);
  • Apelarea setCounter în cadrul funcției handleClick.
const handleClick = () => {
  setCounter(counter + 1);
  console.log(`%c Counter:${counter}`, "color:green");
};

Funcția setCounter va actualiza valoarea contorului cu 1 și va declanșa o re-rendare. Când funcția componentei este apelată la re-rendare, variabila de stare returnată de useState va avea valoarea actualizată.

Încercați CodeSandbox cu codul actualizat. Faceți clic pe butonul Increment și vedeți magia useState în acțiune.

Codesanbox cu useState

Puteți verifica că pe o re-rendare, componenta funcțională ClickCounter este apelat din nou prin vizualizarea jurnalelor consolei. Jurnalul „ClickCounter start” care este adăugat la începutul componentei va fi înregistrat la fiecare randare.

prima redare

redare din nou

Funcția de actualizare

Să presupunem că dorim să creștem valoarea contorului cu 4 la fiecare clic.

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

Să presupunem că valoarea inițială a contorului este 0. Ce vă așteptați să vedeți odată ce ați apăsat butonul?

Fără funcție de actualizare

Te așteptai ca numărul să fie 4, nu? Dar de ce vezi 1 în schimb?

a) Fiecare randare este asociată cu o stare. Valoarea acelei stări rămâne blocată pe durata de viață a acelei randări.

Observați că jurnalul din interiorul funcției handleClick tipărește valoarea contorului ca 0.

Indiferent de câte ori apelați metoda setCounter, valoarea counter rămâne aceeași.

const handleClick = () => {
  setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };
b) Până când tot codul din interiorul unui handler de evenimente este executat, React nu va declanșa o re-rendare.

Din acest motiv, fiecare apel setCounter nu declanșează o randare individuală. În schimb, React adaugă aceste funcții de setare într-o coadă. Le execută în ordinea în care au fost puse la coadă. Actualizările făcute stării după executarea tuturor instrucțiunilor sunt reflectate în randarea următoare. Această coadă a mai multor actualizări de stare este cunoscută ca dozare. Acesta permite React să fie mai performant.

Prin urmare, aici obținem o singură randare în loc de 4 randări diferite.

Acest exemplu este simplu și puteți remedia această problemă actualizând codul după cum se arată mai jos:

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

Dar dacă ați avea un caz de utilizare în care doriți să actualizați starea de mai multe ori înainte de următoarea randare.

Acolo este _ updater Funcția _ este la îndemână.

Putem refactoriza exemplul anterior cu funcția de actualizare după cum urmează:

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

Aici prevCounter ⇒ prevCounter + 1 reprezintă funcția de actualizare.

După cum sa explicat mai devreme, aceste instrucțiuni de actualizare sunt, de asemenea, puse în coadă (grupare).

Funcția de actualizare primește o stare în așteptare/anterioră pe care o folosește pentru a calcula starea următoare.

Funcția de actualizare loturi

Mai jos este CodeSandbox cu funcția de actualizare adăugată. Încercați să faceți clic pe butonul de creștere.

Funcția de actualizare sandbox

Funcția de inițializare

Aruncă o privire la exemplul de mai jos. Aici apelăm funcția getItems pentru a obține valoarea inițială pentru stare.

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;

Această funcție creează o matrice cu dimensiunea 50 și umple matricea cu zerouri. Consultați imaginea de mai jos.

Matrice plină cu 50 de zerouri

Aceste elemente sunt apoi afișate pe ecran.

Totul pare să fie bine, dar avem o problemă aici.

Dati click pe Adaugare element butonul (situat după lista de articole) pentru a adăuga un nou articol la listă. Observați jurnalele.

Fără funcție de inițializare

Vedeți problema aici?

Jurnalul „getItems called” este adăugat în consolă de fiecare dată când adăugați un articol. Aceasta înseamnă că această funcție este apelată la fiecare randare.

Amintiți-vă că useState ignoră valoarea inițială care i-a fost transmisă după prima randare, dar aici valoarea inițială este încă recalculată. Acest lucru poate fi costisitor dacă creăm matrice mari sau efectuăm calcule grele.

Putem rezolva această problemă prin trecere getItems ca un _ initializator _ funcția.

Acum, să facem o mică modificare a codului.

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

Cu funcție de inițializare

Vedeți fereastra consolei în CodeSandbox. Observați că jurnalul „getItems called” este tipărit doar la prima randare. Când sunt adăugate elemente ulterioare, acest jurnal nu este acolo.

Deși nu există o diferență vizuală între cele două exemple, în ceea ce privește performanța, acestea sunt diferite.

Amintiți-vă că atunci când aveți nevoie de o funcție pentru starea inițială, transmiteți întotdeauna funcția sau apelați funcția în interiorul unei alte funcții. Nu apelați niciodată funcția direct.

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

Câte cârlige useState pot avea

Puteți avea câte cârlige useState într-o componentă este nevoie.

Vedeți CodeSandbox

Cârlige de utilizare multiplă

Componenta de mai jos are trei stări diferite – nume de utilizator, parolă, keepMeSignedIn.

Încercați să actualizați valorile numelui de utilizator, keepMeSignedIn. Stările actualizate sunt înregistrate în consolă când se face clic pe butonul de conectare.

Important de subliniat

  • useState oferă un mecanism pentru a declanșa o re-rendare și a persista starea dintre re-rendari.
  • Utilizați funcția de actualizare atunci când aveți nevoie de:
    • Calculați starea următoare pe baza stării anterioare.
    • Efectuați mai multe actualizări ale stării înainte de următoarea randare.
  • Dacă starea inițială este obținută dintr-o funcție – utilizați sintaxa funcției de inițializare.
  • În interiorul unei componente pot exista mai multe cârlige useState.

Ți-a plăcut această postare? Împărtășește-l cu alții.
Scris inițial pentru blogul meu personal – https://gauravsen.com/use-state-hook

Timestamp-ul:

Mai mult de la Codementor React Fapt