Diego Betto's Blog
React 19 - use vs useContext

Diego Betto · 10 settembre 2026 · 6 min di lettura

React 19: `use` vs `useContext`, cosa cambia e quando preferirlo

La nuova use() di React 19 si sovrappone a useContext ma viola di proposito le Rules of Hooks. Differenze spiegate con esempi su contesto e promise.

Condividi:XLinkedInFacebookWhatsApp

React 19 introduce una nuova funzione built-in chiamata use. In superficie sembra un sostituto diretto di useContext — puoi chiamare use(ThemeContext) e ottenere lo stesso valore. Ma use non è un hook, non segue le Rules of Hooks, e fa molto più che leggere il contesto. Se hai già letto la mia guida a useContext, questo è il passo successivo naturale: capire dove si colloca use e quando usarlo porta davvero un vantaggio.

use non è un hook

Ogni hook che conosci — useState, useEffect, useContext — deve essere chiamato incondizionatamente, al livello più alto di un componente, nello stesso ordine ad ogni render. È questa regola che permette a React di tracciare lo stato degli hook in base alla posizione della chiamata. use viola questa regola di proposito: puoi chiamarlo dentro un if, un loop, o dopo un return anticipato.

function Greeting({ showTheme }) {
  // Illegale con useContext, perfettamente valido con use()
  if (showTheme) {
    const theme = use(ThemeContext);
    return <h1>Tema: {theme}</h1>;
  }
  return <h1>Ciao</h1>;
}

React può permetterlo perché use non traccia uno stato tra i render come fa useState — legge un valore che esiste già (un contesto, o il valore risolto di una promise) nel momento in cui viene chiamato. Per questo motivo il team di React ha evitato di chiamarlo useUse o simile: è volutamente esente dalla convenzione di naming use* e dalle sue regole.

ℹ️ Nota

use non può comunque essere chiamato dentro un blocco try/catch, né dentro una funzione JavaScript qualsiasi che non sia un componente o un custom hook — React deve sapere che sta girando dentro un render.

Leggere il contesto: use(Context) vs useContext(Context)

Nel caso semplice sono intercambiabili:

// Con useContext
function Toolbar() {
  const theme = useContext(ThemeContext);
  return <div className={theme}>...</div>;
}

// Con use
function Toolbar() {
  const theme = use(ThemeContext);
  return <div className={theme}>...</div>;
}

La differenza pratica emerge quando la lettura del contesto è condizionale. Immagina un componente che ha bisogno del valore del contesto solo in un ramo:

function Panel({ isExpanded }) {
  // Con useContext devi comunque chiamarlo incondizionatamente,
  // anche se usi il valore solo dentro l'if.
  const theme = useContext(ThemeContext);

  if (!isExpanded) return null;
  return <div className={theme}>Contenuto espanso</div>;
}
function Panel({ isExpanded }) {
  if (!isExpanded) return null;

  // Con use(), leggi il contesto solo quando serve davvero
  const theme = use(ThemeContext);
  return <div className={theme}>Contenuto espanso</div>;
}

Nella maggior parte dei casi le due versioni si comportano allo stesso modo, perché leggere il contesto è un’operazione economica. Il vero vantaggio non è la performance — è poter scrivere componenti la cui logica segue la struttura reale del codice, invece di dover sempre leggere il contesto incondizionatamente in cima.

Leggere le promise con use() e Suspense

È qui che use fa qualcosa che useContext non è mai stato progettato per fare: può “srotolare” una promise, sospendendo il componente finché non si risolve.

function Comments({ commentsPromise }) {
  // `use` sospende questo componente finché la promise non si risolve
  const comments = use(commentsPromise);
  return (
    <ul>
      {comments.map((comment) => (
        <li key={comment.id}>{comment.text}</li>
      ))}
    </ul>
  );
}

function Page({ commentsPromise }) {
  return (
    <Suspense fallback={<p>Caricamento commenti...</p>}>
      <Comments commentsPromise={commentsPromise} />
    </Suspense>
  );
}

Mentre commentsPromise è in sospeso, React mostra il fallback del <Suspense> più vicino. Una volta risolta, Comments viene renderizzato con il valore risolto — niente useEffect, niente stato di caricamento gestito a mano, niente flag isPending da mantenere.

⚠ Importante

Non creare la promise dentro il componente in cui chiami use() — creeresti una nuova promise ad ogni render, innescando un loop infinito di render/sospensione. La promise deve arrivare dall’esterno del render (un Server Component, una cache, o un riferimento stabile creato una sola volta) e passata come prop, come commentsPromise nell’esempio sopra.

Se la promise viene rifiutata, il nearest error boundary la intercetta — un pattern che si lega naturalmente a quanto ho scritto nell’articolo sugli error boundary in React.

use vs useContext a colpo d’occhio

useContext use
Legge il contesto
Legge le promise No
Chiamabile condizionalmente / nei loop No
Segue le Rules of Hooks No (esente di proposito)
Disponibile da React 16.8 React 19
Chiamabile fuori dai componenti No No (serve comunque un contesto di render)

Quindi quale scegliere?

  • Se leggi il contesto incondizionatamente in cima al componente, useContext va benissimo ed è perfettamente idiomatico — non serve riscrivere codice esistente solo perché use esiste.
  • Passa a use quando la lettura del contesto è davvero condizionale, o deve stare dentro un loop o dopo un return anticipato.
  • Passa a use quando devi srotolare una promise durante il render — tipicamente dati passati giù da un Server Component o una fetch fatta in cache fuori dal componente — e vuoi che Suspense gestisca lo stato di caricamento al posto tuo.

💡 Consiglio

use si integra bene con il pattern in cui un Server Component avvia un fetch di dati, passa giù la promise non ancora risolta come prop, e un Client Component chiama use() su di essa per mostrare la UI non appena è pronta — senza bloccare il render iniziale della pagina. Questo pattern è centrale nei React Server Components, che tratto in un articolo dedicato.

FAQ

❓ Posso sostituire tutti i miei useContext con use?

Sì, dal punto di vista sintattico use(Context) e useContext(Context) restituiscono lo stesso valore. Ma non c’è nessun vantaggio nel sostituire chiamate già incondizionate in cima al componente — fallo solo dove ti serve davvero la flessibilità della chiamata condizionale o il supporto alle promise che use aggiunge.

❓ use() sostituisce useEffect + fetch per il data fetching nei Client Components?

Solo in parte. use() srotola una promise che già hai — non avvia il fetch di per sé. Serve comunque qualcosa che crei quella promise (un Server Component, un’API di data-loading del framework, o una cache). Pensa a use come al lato “consumo” dei dati asincroni, non come a una libreria di fetching.

❓ use() è un Hook di React?

No. React lo documenta intenzionalmente come un’API che “usa” una risorsa, non un hook — per questo non segue le Rules of Hooks e non compare insieme a useState/useEffect nel riferimento degli hook.

Conclusione

use e useContext si sovrappongono nella lettura del contesto, ma use è lo strumento più flessibile e generale — chiamate condizionali, loop, supporto alle promise — al costo di essere un’API più nuova e meno collaudata. Tieni useContext per i casi semplici che già hai; passa a use quando la logica del componente ha davvero bisogno di quella flessibilità, o quando stai collegando data fetching basato su Suspense.

Riferimenti

Condividi:XLinkedInFacebookWhatsApp
Diego Betto

Scritto da

Diego Betto

Co-Fondatore & CTO presso PAPION. Senior full-stack engineer specializzato in React, TypeScript, Node.js e sicurezza applicativa.