State: La Memoria di un Componente
Spesso i componenti devono modificare ciò che c’è sullo schermo in seguito a un’interazione. Scrivere nel form deve aggiornare l’input, cliccare “avanti” su un carosello deve cambiare l’immagine mostrata, cliccare “acquista” inserisce un prodotto nel carrello. I componenti devono “ricordare” le cose: l’attuale valore dell’input, l’attuale immagine, il carrello. In React, questo specifico tipo di memoria è detto state.
Imparerai
- Come aggiungere una variabile state con l’Hook
useState
- Quale coppia di valori restituisce l’Hook
useState
- Come aggiungere più di una variabile state
- Perché lo state si definisce locale
Quando una variabile normale non è sufficiente
Ecco un componente che renderizza l’immagine di una scultura. Cliccare sul pulsante “Next” dovrebbe mostrare la scultura successiva, modificando l’index
a 1
, poi 2
, e così via. Tuttavia, questo non funzionerà (puoi provare!):
L’event handler handleClick
sta aggiornando una variabile locale, index
. Ma due cose impediscono alla modifica di essere visibile:
- Le variabili locali non persistono tra le renderizzazioni. Quando React renderizza questo componente una seconda volta, lo renderizza da zero e non considera eventuali modifiche alle variabili locali.
- Le modifiche alle variabili locali non triggerano il render. React non si accorge di dover renderizzare un’altra volta il componente con i dati nuovi.
Per aggiornare un componente con nuovi dati, devono accadere due cose:
- Conservare i dati tra le renderizzazioni.
- Triggerare React per renderizzare il componente con nuovi dati (re-renderizzazione).
L’Hook useState
offre queste due cose:
- Una variabile state per conservare i dati tra le renderizzazioni.
- Una funzione state setter per aggiornare la variabile e triggerare React per renderizzare di nuovo il componente.
Aggiungere una variabile state
Per aggiungere una variabile state, importa useState
da React in cima al file:
import { useState } from 'react';
Poi, sostituisci questa riga:
let index = 0;
con
const [index, setIndex] = useState(0);
index
è una variabile state e setIndex
è la funzione setter.
La sintassi
[
e]
è chiamata destrutturazione di un array e ti consente di leggere i valori di un array. L’array ritornato dauseState
ha sempre esattamente due elementi.
Ecco come funzionano insieme in handleClick
:
function handleClick() { setIndex(index + 1); }
Ora cliccare sul pulsante “Next” modifica la scultura corrente:
Ecco il tuo primo Hook
In React, useState
, così come qualsiasi altra funzione che inizia per ”use
”, è chiamata Hook.
Gli Hook sono funzioni speciali disponibili solo durante la fase di renderizzazione di React (che vedremo nel dettaglio nella pagina successiva). Ti consentono di “agganciarti” a diverse funzionalità di React.
Lo State è solo una di queste funzionalità, ma incontrerai gli altri Hook più avanti.
Anatomia di useState
Quando chiami useState
, stai dicendo a React che vuoi che questo componente ricordi qualcosa:
const [index, setIndex] = useState(0);
In questo caso, vuoi che React ricordi index
.
L’unico argomento di useState
è il valore iniziale della tua variabile state. In questo esempio, il valore iniziale di index
è impostato a 0
con useState(0)
.
Ogni volta che il tuo componente renderizza, useState
ti da un array contenente due valori:
- La variabile state (
index
) con il valore che hai memorizzato. - La funzione state setter (
setIndex
) che può aggiornare la variabile state e triggerare React a renderizzare di nuovo il componente.
Ecco come questo accade in azione:
const [index, setIndex] = useState(0);
- Il tuo componente renderizza per la prima volta. Poiché hai passato
0
auseState
come valore iniziale diindex
, questo ritornerà[0, setIndex]
. React ricorda che0
è l’ultimo valore dello state. - Aggiorni lo state. Quando un utente clicca il pulsante, questo chiama
setIndex(index + 1)
.index
è0
, quindi diventasetIndex(1)
. Questo dice a React di ricordare cheindex
ora è1
e di triggerare un’altra renderizzazione. - La seconda renderizzazione del tuo componente. React ancora vede
useState(0)
, ma poiché React ricorda che hai impostatoindex
a1
, ritorna invece[1, setIndex]
. - E così via!
Dare a un componente più variabili state
Puoi avere quante variabili state di quanti tipi desideri in un componente. Questo componente ha due variabili state, un numero index
e un booleano showMore
che viene invertito quando clicchi “Show details”:
È una buona idea avere più variabili state se il loro state non è correlato, come index
e showMore
in questo esempio. Ma se ti rendi conto che modifichi spesso due variabili state allo stesso tempo, potrebbe essere più semplice unirle in una sola. Ad esempio, se hai un form con molti campi, è più conveniente avere una singola variabile state che contiene un oggetto piuttosto che una variabile state per ogni campo. Leggi Scegliere la Struttura dello State per altri consigli.
Deep Dive
Avrai notato che la chiamata useState
non riceve alcuna informazione circa quale variabile di stato prendere come riferimento. Non viene passato alcun “identificatore” a useState
, quindi come fa a sapere quale delle variabili di stato restituire? Fa affidamento su qualche magia come il parsing delle tue funzioni? La risposta è no.
Invece, per consentire la loro sintassi concisa, gli Hook si basano su un ordine di chiamata stabile a ogni renderizzazione dello stesso componente. Questo funziona bene in pratica perché se segui la regola sopra (“chiamare solo gli Hook al livello superiore”), gli Hook verranno sempre chiamati nello stesso ordine. Inoltre, un plugin linter rileva la gran parte degli errori.
Internamente, React mantiene un array di coppie di stato per ogni componente. Mantiene anche l’indice della coppia corrente, che viene impostato su 0
prima della renderizzazione. Ogni volta che chiami useState
, React ti fornisce la coppia di stato successiva e incrementa l’indice. Puoi leggere di più su questo meccanismo in React Hook: Non Magia, Solo Array.
Questo esempio non utilizza React ma ti dà un’idea di come useState
funzioni internamente:
Non è necessario che tu lo capisca per utilizzare React, ma potresti trovare utile questo modello mentale.
Lo State è isolato e privato
Lo State è locale rispetto all’istanza di un componente sullo schermo. In altre parole, se renderizzi lo stesso componente due volte, ogni copia avrà uno state completamente isolato! Modificare uno dei due non intaccherà l’altro.
In questo esempio, il componente Gallery
di prima viene renderizzato due volte con nessuna modifica apportata alla sua logica. Prova a cliccare sui bottoni all’interno di entrambe le gallerie. Nota come i loro state sono indipendenti:
Questo è ciò che rende lo state diverso dalle variabili regolari che potresti dichiarare in cima al tuo modulo. Lo state non è legato a una particolare chiamata di funzione o a un luogo nel codice, ma è “locale” rispetto a un preciso posto sullo schermo. Hai renderizzato due componenti <Gallery />
, quindi il loro state viene memorizzato separatamente.
Inoltre nota come il componente Page
non “sa” nulla dello state di Gallery
ne tantomeno se ne ha uno. A differenza delle prop, lo state è totalmente privato rispetto al componente che lo dichiara. Il componente padre non può modificarlo. Questo ti consente di aggiungere lo state a qualsiasi componente o rimuoverlo, senza avere alcun impatto sul resto dei tuoi componenti.
E se volessi che entrambe le gallerie mantenessero lo state sincronizzato? Il modo corretto per fare questo in React è rimuovere lo state dai componenti figli e aggiungerlo al padre comune più vicino. Le prossime pagine si focalizzeranno sull’organizzazione dello state in un singolo componente, ma torneremo su questo argomento in Condividere lo State tra Componenti.
Riepilogo
- Usa una variabile state quando un componente deve “ricordare” qualche informazione tra le renderizzazioni.
- Le variabili state sono dichiarate chiamando l’Hook
useState
. - Gli Hook sono funzioni speciali che iniziano per
use
. Ti consentono di “agganciarti” alle funzionalità di React come lo state. - Gli Hook potrebbero ricordati gli import: devono essere chiamati incondizionatamente. Chiamare gli Hook, incluso
useState
, è valido solo al livello superiore del componente o di un altro Hook. - L’Hook
useState
ritorna una coppia di valori: lo state attuale e la funzione per aggiornarlo. - Puoi avere più di una variabile state. Internamente, React le distingue in base all’ordine.
- Lo state è privato rispetto al componente. Se quest’ultimo lo renderizzi in due posti, ogni copia avrà il suo state.
Sfida 1 di 4: Completa la galleria
Quando, arrivato all’ultima scultura, clicchi su “Next”, il codice va in errore. Correggi la logica per prevenire l’errore. Potresti aggiungere della logica in più nell’event handler o disabilitare il pulsante quando l’azione non è possibile.
Una volta risolto l’errore, aggiungi un pulsante “Previous” che mostra la scultura precedente. Non dovrebbe andare in errore quando si è sulla prima scultura.