Vai al contenuto principale

Come usare le context API in React

Scopri come utilizzare le Context API e useReducer in React per una gestione dello stato globale efficiente e organizzata, ideale per app complesse.

Le Context API in React rappresentano un meccanismo efficace per il "prop drilling", ovvero la pratica di passare i dati da un componente all'altro attraverso le props, anche quando ciò non è strettamente necessario. Invece di passare i props a tutti i livelli dell'applicazione, le Context API permettono di condividere valori direttamente tra i componenti, senza doverli passare esplicitamente attraverso ogni livello dell'albero dei componenti. Questo rende molto più semplice la gestione dello stato globale dell'applicazione, specialmente in progetti di grandi dimensioni.

Come Funzionano le Context API

Le Context API funzionano creando un "contexto", che è un modo per condividere i valori tra i componenti senza dover utilizzare le props. Un contesto può essere definito utilizzando React.createContext(), e ha due parti principali: il Provider e il Consumer.

  • Provider: Un componente che fornisce il valore del contesto ai suoi componenti figli. Tutti i componenti figli, indipendentemente da quanto profondamente sono annidati, possono accedere a questo valore senza doverlo ricevere esplicitamente come prop.
  • Consumer: Un componente che consuma il valore fornito dal Provider. In alternativa, si può utilizzare l'hook useContext per accedere al valore del contesto in componenti funzionali.

Gestione dello stato complessa

Quando si ha a che fare con una logica di stato più complessa, combinare useContext con useReducer in React può offrire un approccio più strutturato e scalabile. Questo metodo è particolarmente utile per gestire stati globali che richiedono diverse azioni per essere aggiornati in maniera prevedibile.

Gestione dello Stato di Autenticazione

In questo esempio, creeremo un contesto di autenticazione per un'applicazione, utilizzando useContext per accedere allo stato e alle azioni di autenticazione, e useReducer per gestire le modifiche allo stato.

Definizione del Reducer e del Contexto

Primo, definiamo il reducer e il contesto. Creeremo un file AuthContext.tsx.

import React, { createContext, useContext, useReducer, ReactNode } from 'react';

type AuthState = {
  isAuthenticated: boolean;
};

type AuthAction =
  | { type: 'LOGIN' }
  | { type: 'LOGOUT' };

const initialState: AuthState = {
  isAuthenticated: false,
};

const AuthContext = createContext<{ state: AuthState; dispatch: React.Dispatch<AuthAction> } | undefined>(undefined);

function authReducer(state: AuthState, action: AuthAction): AuthState {
  switch (action.type) {
    case 'LOGIN':
      return { ...state, isAuthenticated: true };
    case 'LOGOUT':
      return { ...state, isAuthenticated: false };
    default:
      return state;
  }
}

export const AuthProvider = ({ children }: { children: ReactNode }) => {
  const [state, dispatch] = useReducer(authReducer, initialState);

  return (
    <AuthContext.Provider value={{ state, dispatch }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
};

Qui, AuthContext è il contesto che abbiamo creato, che conterrà lo stato di autenticazione e una funzione dispatch per eseguire azioni. AuthProvider è il componente che useremo per avvolgere la parte dell'applicazione che ha bisogno di accedere a queste informazioni. useAuth è un hook personalizzato che facilita l'accesso al contesto di autenticazione.

Utilizzo del Contexto di Autenticazione

Per utilizzare il contesto, avvolgiamo i nostri componenti con AuthProvider nel punto più alto possibile dell'albero dei componenti, tipicamente in App.tsx.

import React from 'react';
import { AuthProvider } from './AuthContext';
import LoginComponent from './LoginComponent';

function App() {
  return (
    <AuthProvider>
      <LoginComponent />
    </AuthProvider>
  );
}

export default App;

E infine, un componente che utilizza useAuth per effettuare il login e il logout:

import React from 'react';
import { useAuth } from './AuthContext';

const LoginComponent = () => {
  const { state, dispatch } = useAuth();

  return (
    <div>
      {state.isAuthenticated ? (
        <>
          <p>Sei autenticato!</p>
          <button onClick={() => dispatch({ type: 'LOGOUT' })}>Logout</button>
        </>
      ) : (
        <>
          <p>Non sei autenticato.</p>
          <button onClick={() => dispatch({ type: 'LOGIN' })}>Login</button>
        </>
      )}
    </div>
  );
};

export default LoginComponent;

In questo componente, usiamo useAuth per accedere allo stato di autenticazione e alla funzione dispatch. I pulsanti permettono all'utente di effettuare il login o il logout, triggerando un cambiamento nello stato globale di autenticazione che si riflette in tutta l'applicazione.

Conclusione

L'uso combinato di useContext e useReducer fornisce un potente strumento per gestire lo stato complesso in modo più prevedibile e organizzato. Questo pattern è particolarmente utile per gestire stati globali in applicazioni grandi e complesse, offrendo una chiara separazione tra la logica di gestione dello stato e l'interfaccia utente.

Unisciti a WebTea

Niente spam. Solo contenuti formativi su Software Engineering.

Ci sono due cose che non ci piacciono: lo spam e il mancato rispetto della privacy. Seleziona come vuoi restare in contatto:

Preferenze di contatto

Usiamo Mailchimp come piattaforma di marketing. Cliccando su iscriviti, accetti la nostra privacy policy e che le tue informazioni vengano trasferite a Mailchimp per l'elaborazione. Termini e Privacy. Puoi disiscriverti in qualsiasi momento.