React è una popolare libreria JavaScript utilizzata per la creazione di interfacce utente. Offre a sviluppatrici e sviluppatori un’ampia gamma di strumenti, tra cui gli hook, che permettono di creare applicazioni in modo più semplice ed efficiente.

Uno degli hook più utilizzati è useState, che permette di aggiungere uno stato ai componenti funzionali.

In questo articolo offriremo un’analisi approfondita di useState, analizzandone impieghi e best practice.

Cos’è l’hook useState?

Prima di addentrarci nelle specifiche di useState, definiamo innanzitutto gli hook e quali sono le differenze rispetto ai tradizionali componenti di classe.

Un hook è una funzione che permette di utilizzare lo stato e altre caratteristiche di React in componenti funzionali.

A differenza dei componenti di classe, i componenti funzionali non possono memorizzare lo stato. Gli hook come useState risolvono questo problema permettendo di aggiungere lo stato ai componenti funzionali.

Il backgroung dell’hook useState

Prima dell’introduzione dell’hook useState in React 16.8, i componenti funzionali non erano in grado di conservare il proprio stato. Gli sviluppatori dovevano invece utilizzare componenti di classe o librerie esterne di gestione dello stato come Redux per gestire lo stato nelle applicazioni.

Sebbene i componenti di classe e le librerie esterne di gestione dello stato siano ancora soluzioni valide, l’introduzione dell’hook useState ha reso molto più semplice aggiungere lo stato ai componenti funzionali e ha semplificato l’API di React nel suo complesso.

Con l’hook useState gli sviluppatori possono utilizzare i componenti funzionali nella maggior parte delle applicazioni, riducendo la quantità di codice boilerplate necessario e rendendo più semplice la valutazione dello stato.

Elementi della sintassi useState

L’hook useState prende come argomento un valore di stato iniziale e restituisce un array contenente due elementi: il valore di stato corrente e una funzione che aggiorna il valore di stato.

Ecco la sintassi:

const [state, setState] = useState(initialState);
  • state: il valore corrente dello stato.
  • setState: una funzione che aggiorna il valore dello stato.
  • initialState: il valore iniziale della variabile di stato che si sta dichiarando. È facoltativo. Se non viene fornito alcun valore (non è consigliabile), questo viene automaticamente impostato su undefined.

È importante notare che, quando si utilizza l’hook useState, ogni volta che il valore dello stato cambia, React eseguirà automaticamente un nuovo rendering del componente.

Come utilizzare l’hook useState

Per utilizzare useState, bisogna invocare la funzione e passarle un valore iniziale come argomento. La funzione restituisce un array contenente il valore dello stato corrente e una funzione per aggiornare lo stato.

Ecco un esempio per la gestione di un semplice contatore:

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

export default Counter;

In questo esempio, inizializziamo lo stato di count a 0 utilizzando useState. Poi renderizziamo il valore del conteggio corrente e un pulsante. Quando il pulsante viene cliccato, il valore del conteggio sarà incrementato perché abbiamo aggiunto una funzione freccia con la funzione setCount.

<button onClick={() => setCount(count + 1)}>Click me</button>

Quando si usa l’hook useState, è importante ricordare di importarlo dalla libreria React. Se ci si dimentica di importarlo, è probabile che si verifichino degli errori. Ecco come importare useState:

import { useState } from 'react';

Includendo useState nella dichiarazione di importazione, stiamo dicendo a React che vogliamo utilizzare l’hook useState nel nostro componente.

Utilizzare diversi tipi di dati in React con useState

L’hook useState di React non si limita a gestire solo i tipi di dati stringa o numerici. È possibile utilizzarlo per gestire gli stati di diversi tipi di dati, come array, oggetti e booleani.

Utilizzare gli array con l’hook useState

È possibile utilizzare l’hook useState per gestire un array in React. Ad esempio, se abbiamo un array di frutti, possiamo inizializzare lo stato con l’array:

import { useState } from 'react';

function App() {
  const [list, setList] = useState(['apple', 'banana', 'orange']);

  const addToList = () => {
    const newItem = 'grape';
    setList([...list, newItem]);
  };

  return (
    <div>
      <ul>
        {list.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
      <button onClick={addToList}>Add Item</button>
    </div>
  );
}

export default App;

In questo esempio, utilizziamo useState per gestire un array chiamato list. Lo stato iniziale di list è impostato su un array contenente tre elementi: apple, banana e orange.

Abbiamo anche creato una funzione addToList che copia tutti gli elementi dell’array con l’operatore spread (...) e poi aggiunge un nuovo elemento grape all’array list ogni volta che viene cliccato il pulsante “Aggiungi elemento”.

Questa volta non aggiorneremo lo stato in linea utilizzando una funzione freccia perché è più opportuno creare questa operazione come funzione indipendente e invocarla attraverso il metodo onClick aggiunto al pulsante Aggiungi elemento.

Utilizzare gli oggetti con useState

Possiamo utilizzare l’hook useState anche per gestire un oggetto in React. Ecco un esempio:

import { useState } from 'react';

function App() {
  const [user, setUser] = useState({ name: 'John', age: 30 });

  const handleClick = () => {
    setUser({ ...user, age: user.age + 1 });
  };

  return (
    <div>
      <p>Name: {user.name}</p>
      <p>Age: {user.age}</p>
      <button onClick={handleClick}>Increase Age</button>
    </div>
  );
}

export default App;

In questo esempio, utilizziamo useState per gestire un oggetto chiamato user. Lo stato iniziale di user è impostato su un oggetto contenente due proprietà: name e age.

Abbiamo anche una funzione handleClick che copia tutti i dati dell’oggetto con l’operatore di diffusione (...) e aumenta l’età dell’utente di 1 ogni volta che viene cliccato il pulsante Increase Age.

È importante sapere che è possibile assegnare questo oggetto a una variabile e poi inizializzare la variabile. Questo è utile quando si ha un oggetto o un array di grandi dimensioni e si vuole scrivere un codice di facile comprensione:

import { useState } from 'react';
// Declare data
let userData = {
    name: 'John',
    age: 30,
};

function App() {
    const [user, setUser] = useState(userData);

    const handleClick = () => {
        setUser({ ...user, age: user.age + 1 });
    };

    return (
        <div>
            <p>Name: {user.name}</p>
            <p>Age: {user.age}</p>
            <button onClick={handleClick}>Increase Age</button>
        </div>
    );
}

export default App;

Utilizzare i booleani con useState

Si può anche utilizzare l’hook useState per gestire un valore booleano. Ecco un esempio:

import { useState } from 'react';

function App() {
  const [isOn, setIsOn] = useState(false);

  const toggleSwitch = () => {
    setIsOn(!isOn);
  };

  return (
    <div>
      <p>The switch is {isOn ? 'on' : 'off'}</p>
      <button onClick={toggleSwitch}>Toggle Switch</button>
    </div>
  );
}

export default App;

In questo esempio, utilizziamo useState per gestire un valore booleano chiamato isOn. Lo stato iniziale di isOn è impostato su false. Abbiamo anche una funzione toggleSwitch che altera il valore di isOn ogni volta che viene cliccato il pulsante Toggle Switch.

Questa funzione può essere utilizzata per gestire l’alternanza delle modalità scura e chiara nei progetti.

Prima di concludere, analizziamo un utilizzo più avanzato dell’hook useState con i moduli.

L’hook useState e i moduli

Per gestire i dati dei moduli e gli input degli utenti in React, si utilizza lo stato. Questo viene utilizzato per tenere traccia dei valori correnti degli elementi del modulo. Tiene traccia di tutte le interazioni dell’utente, come la digitazione di un input di testo o la selezione di un’opzione da un menu a tendina, e infine aggiorna lo stato con il nuovo valore.

Ecco un esempio di utilizzo di useState per la creazione di un semplice modulo:

import { useState } from 'react';

let formStateData = {
    firstName: '',
    lastName: '',
    email: '',
};

function Form() {
    const [formData, setFormData] = useState(formStateData);

    const handleInputChange = (event) => {
        const { name, value } = event.target;
        setFormData({ ...formData, [name]: value });
    };

    const handleSubmit = (event) => {
        event.preventDefault();
        console.log(formData);
    };

    return (
        <form onSubmit={handleSubmit}>
            <input
                type="text"
                name="firstName"
                value={formData.firstName}
                onChange={handleInputChange}
            />
            <input
                type="text"
                name="lastName"
                value={formData.lastName}
                onChange={handleInputChange}
            />
            <input
                type="email"
                name="email"
                value={formData.email}
                onChange={handleInputChange}
            />
            <button type="submit">Submit</button>
        </form>
    );
}

export default Form;

In questo esempio, creiamo innanzitutto un oggetto per i dati che verranno raccolti con il modulo, con valori predefiniti per i campi firstName, lastName e email. Poi inizializziamo lo stato formData utilizzando useState.

let formStateData = {
    firstName: '',
    lastName: '',
    email: '',
};

const [formData, setFormData] = useState(formStateData);

Definiamo poi una funzione handleInputChange che aggiorna lo stato formData ogni volta che un campo del modulo viene modificato.

const handleInputChange = (event) => {
    const { name, value } = event.target;
    setFormData({ ...formData, [name]: value });
};

Infine, definiamo una funzione handleSubmit che registra i dati correnti del modulo nella console quando il modulo viene inviato.

const handleSubmit = (event) => {
    event.preventDefault();
    console.log(formData);
};

Best practice di useState

Quando si utilizza l’hook useState, è importante seguire le best practice per evitare errori e garantire prestazioni ottimali. Ecco alcuni suggerimenti:

  • Evitare stati annidati profondamente: invece di memorizzare dati di stato complessi in un unico oggetto, è bene valutare la possibilità di suddividerli in parti più piccole per semplificarne la gestione.
  • Utilizzare aggiornamenti funzionali: quando si aggiorna lo stato in base allo stato precedente, è bene utilizzare gli aggiornamenti funzionali per evitare race condition e garantire che venga aggiornato lo stato corretto.
  • Evitare aggiornamenti eccessivi dello stato: l’aggiornamento dello stato può essere dispendioso, quindi è bene cercare di ridurre al minimo il numero di aggiornamenti. Si può prendere in considerazione l’hook useEffect per raggruppare gli aggiornamenti e ottimizzare le prestazioni.
  • Evitare i re-rendering non necessari: React esegue un nuovo rendering di un componente ogni volta che lo stato o le proprietà cambiano. Per evitare i re-rendering non necessari, si può utilizzare la funzione memo.

Riepilogo

In questo articolo abbiamo analizzato l’hook useState e abbiamo visto come utilizzarlo per aggiungere lo stato ai componenti funzionali. Abbiamo anche visto come utilizzare useState con moduli, array e oggetti e suggerito alcune best practice per ottenere prestazioni ottimali. Seguendole, potrete creare applicazioni React efficienti, scalabili e facili da mantenere.

State cercando la soluzione di hosting ideale per le vostre applicazioni React? Provate gratuitamente l’Hosting di Applicazioni di Kinsta!