Che cos’è lo stato di un componente in React | Aulab

GUIDE PER ASPIRANTI PROGRAMMATORI

Che cos’è lo stato di un componente in React

Lo stato di un componente in React è la rappresentazione del componente in un momento specifico del tempo, tipicamente adesso. “Adesso” inteso come il momento in cui si guarda lo stato. Facciamo, come prima cosa, un esempio pratico; parleremo del concetto teorico nella prossima sezione.  L’esempio in questione è il più classico degli esempi in…

Lezione 13 / 41
Enza Neri
Immagine di copertina

Vuoi avviare una nuova carriera o fare un upgrade?

Trova il corso Digital & Tech più adatto a te nel nostro catalogo!

Lo stato di un componente in React è la rappresentazione del componente in un momento specifico del tempo, tipicamente adesso. “Adesso” inteso come il momento in cui si guarda lo stato.

Facciamo, come prima cosa, un esempio pratico; parleremo del concetto teorico nella prossima sezione.  L’esempio in questione è il più classico degli esempi in React.

Immaginiamo di voler creare un contatore.
Vogliamo due bottoni, uno che dice più (+) e uno che dice meno (-). Il contatore inizia con valore zero. Il bottone che dice + aumenta di uno il valore del contatore, il bottone che dice – diminuisce di uno il valore del contatore. Il contatore non scende mai sotto zero. Lasciamo da parte, per un attimo, le props e gli eventi, inserendo l’intera logica nel componente contatore, mentre App non farà altro che ospitarlo.

Iniziamo creando un componente che mostra solo l’interfaccia.
Possiamo inserirlo nella cartella components e chiamarlo Counter. Creiamo anche un file Counter.css relativo. Possiamo tenere l’elemento Panel, ma dobbiamo ricordarci di rimuovere il controllo che non permette a Panel di avere componenti figli che non siano Message, altrimenti ci troveremo un errore.

// File: src/components/Counter.jsx

import "./Counter.css";

export default function Counter() {
  return (
    <div className="Counter">
      <button>-</button>
      <span>0</span>
      <button>+</button>
    </div>
  );
}
/* File: src/components/Counter.css */

.Counter > * + * {
  margin-left: 0.5em;
}
// File: src/App.jsx

import "./App.css";
import Counter from "./components/Counter";
import Panel from "./components/Panel";

export default function App() {
  return (
    <div className="App">
      <Panel>
        <Counter />
      </Panel>
    </div>
  );
}
// File: arc/components/Panel.jsx

import "./Panel.css";

export default function Panel({ children }) {
  return <div className="Panel">{children}</div>;
}

Ragioniamo, ora, sulla struttura del counter:

  • Il numero al centro rappresenta il valore del contatore “adesso”. È il nostro stato!
  • Il bottone che dice – deve togliere uno al valore del contatore, a meno che il valore non sia zero. In altre parole, se il valore del contatore è diverso da zero, lo diminuisce di uno.
  • Il bottone che dice + deve aggiungere uno al valore del contatore.

Ecco il codice che rappresenta queste funzionalità:

// File: src/components/Counter.jsx

import "./Counter.css";
import { useState } from "react";

export default function Counter() {
  const [value, setValue] = useState(0);

  const onMinusButtonClick = () => {
    if (value !== 0) {
      setValue((value) => {
        return value - 1;
      });
    }
  };

  const onPlusButtonClick = () => {
    setValue((value) => {
      return value + 1;
    });
  };

  return (
    <div className="Counter">
      <button onClick={onMinusButtonClick}>-</button>
      <span>{value}</span>
      <button onClick={onPlusButtonClick}>+</button>
    </div>
  );
}

Analizziamo il codice soprastante:

  • useState è la funzione importata da React che ci permette di creare uno stato. La funzione prende come argomento lo stato iniziale, in questo caso 0. Lo stato iniziale è il valore che ha lo stato nel momento in cui il componente viene creato. Il valore iniziale di useState può anche essere calcolato con una funzione, in questo caso passiamo una funzione callback a useState (useState(() => { /* qui calcoliamo lo stato */ })). Attenzione: quando usiamo una funzione per calcolare il valore iniziale dello stato, la funzione deve essere sincrona (i.e.: non possiamo usare async o una Promise). Per gestire stati asincroni, ci sono delle teniche che vedremo nelle prossime sezioni.
  • useState restituisce un array con due valori al suo interno. Il primo valore della coppia restituita da useState è il valore dello stato “adesso”. Il secondo valore della coppia restituita da useState è una funzione, che possiamo chiamare setter (“impostatrice”).

    La funzione setter serve a impostare il valore che lo stato avrà “dopo”, il prossimo valore. La funzione setter non restituisce nulla. Inoltre, è bene precisare che la funzione setter è una funzione di ordine superiore e gli sviluppatori di React incoraggiano l’utilizzo di una callback (così come mostrato negli esempi precedenti per incrementare o decrementare un valore)
  • Usiamo la destruttrazione per estrarre i valori della coppia restituita da useState. Avremmo potuto scrivere una cosa come const valueState = useState(0);, e poi chiamare il valore valueState[0] e la funzione setter valueState[1]. Invece, per comodità, desctrutturiamo la coppia con const [value, setValue] = useState(0);.
  • I nomi che abbiamo dato ai valori della coppia restituita da useState sono più o meno arbitrari. È convenzionale, in React, chiamare la funzione setter con set seguito dal nome dello stato (per esempio [message, setMessage], [isVisible, setIsVisible]). Abbiamo scelto value perché lo stato rappresenta il valore del contatore. Essendo all’interno del componente Counter il fatto che il valore sia “del contatore” è implicito (per cui non abbiamo scelto, per esempio, counterValue).
  • Definiamo due event listener. All’interno, chiamiamo la funzione setter con il valore che lo stato dovrà avere “dopo”, vale a dire il prossimo valore. Nel caso di onMinusButtonClick, se il valore di “adesso” è diverso da zero (cioè maggiore o uguale a zero, perché – ricordiamo – il valore non scende mai sotto zero), allora il prossimo valore è il valore di “adesso”, meno uno. Nel caso di onPlusButtonClick, il prossimo valore è sempre il valore “attuale”, più uno.

Immutabilità dello stato di un componente in React e callback

Ci sono due cose estremamente importanti da sapere sugli stati di React:

  1. Lo stato è immutabile. Questo vuol dire che il valore dello stato (in questo caso value) non può essere modificato direttamente: per modificarlo, utilizziamo la funzione setter. Che lo stato sia un valore primitivo – come una stringa o un numero – o che sia una struttura come un array o un oggetto, modificare direttamente il valore dello stato (per esempio con value = 42 o value++) non ha nessun effetto. Il perché lo scopriremo nelle prossime sezioni.
  2. La funzione setter può essere chiamata in due modi: passando direttamente il prossimo valore dello stato, per esempio setValue(0), oppure, come nell’esempio soprastante, passando una funzione che prende come argomento il valore dello stato “adesso” e restituisce il prossimo valore.

    Si utilizza la seconda forma quando il prossimo valore dello stato dipende da quello corrente, quando il valore corrente ci serve per calcolare il prossimo. Si utilizza la prima forma quando il valore corrente non è importante, quando il prossimo valore dello stato è costante.

Quando il calcolo del prossimo valore dello stato contiene il valore corrente, cioè quando il prossimo valore dello stato dipende da quello di “adesso”, è importante utilizzare la forma setState((currentStateValue) => { return nextStateValue; }); invece della forma setState(nextStateValue);.

Anche se il valore corrente dello stato potrebbe essere a nostra disposizione nel momento in cui chiamiamo la funzione setter, ci sono dei casi in cui questo valore potrebbe non essere aggiornato. Per evitare il problema, se il valore dello stato “adesso” ci serve per calcolare quello “dopo”, chiamiamo sempre la funzione setter passando una funzione.

Sei indeciso sul percorso? 💭

Parliamone! Scrivici su Whatsapp e risponderemo a tutte le tue domande per capire quale dei nostri corsi è il più adatto alle tue esigenze.

Oppure chiamaci al 800 128 626