# Suspense: what it suspends and what it does not

Suspense shows a fallback while a component waits for a promise: it works with lazy and use, not with a fetch started inside useEffect.

> Page: https://ui.eneawork.it/blog/react-suspense-base
> Markdown: https://ui.eneawork.it/blog/react-suspense-base.md

*2026-11-01*

Suspense sospende solo un componente che lancia una promessa durante il render: React mostra il fallback e riprova quando la promessa si risolve. Una fetch avviata dentro useEffect non sospende nulla.

Il catalogo EneUI conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, misurati da /api/stats il 1 novembre 2026. La cifra viene da una query all'endpoint, non da una stima: conta i record pubblicati, non la qualità dei componenti.

## Cosa sospende davvero

Tre casi entrano nel meccanismo: lazy() che carica un modulo, use(promise) di React 19 che legge una promessa già creata, e le librerie dati che lanciano la promessa al posto tuo. Tutto il resto resta stato normale.

## Un caso eseguibile

import { Suspense, lazy } from "react"; const Pannello = lazy(() => import("./Pannello")); export function Scheda({ aperta }) { if (!aperta) return null; return ( Caricamento}> ); }

Il file gira in un progetto Vite con React 19: Suspense avvolge il componente pigro e il fallback appare finché il modulo non arriva. Il resto della pagina resta interattivo.

## Skeleton o testo

Il fallback è interfaccia: uno skeleton che conserva l'altezza evita il salto di layout, un testo breve costa meno da leggere. In entrambi i casi il contenuto deve avere dimensioni stabili, altrimenti il Cumulative Layout Shift peggiora proprio dove volevi migliorare.

## Record vivi nel catalogo

La categoria skeleton raccoglie i segnaposto del catalogo, con uno skeleton di blocco già pronto; per un'attesa breve c'è lo spinner di Kibo UI, licenza MIT.

## La limitazione

Suspense non scarica dati da solo e non riprova una promessa rifiutata: un errore dentro il sottoalbero sospeso richiede un error boundary, altrimenti la pagina resta sul fallback. Non esiste un timeout configurabile, quindi non puoi dire a React di aspettare al massimo duecento millisecondi.

## Dove continuare

Lo streaming con Suspense è in streaming e Suspense in Next.js; il modello dei server component è in guida ai server component; le novità della versione sono in React 19, cosa cambia. Il confronto fra i due framework più diffusi è in Vue 3 vs React.

## FAQ

### Suspense funziona con una fetch in useEffect?

No. Una fetch avviata in useEffect non lancia promesse durante il render, quindi Suspense non la vede e mostra lo stato di caricamento che hai scritto.

### Serve React 19 per usare Suspense?

No per lazy, sì per use. Suspense esiste dalla 16.6 e carica componenti pigri; la lettura di una promessa con use richiede React 19.

### Che differenza c'è fra Suspense e un if di caricamento?

Il controllo sta dove nasce la promessa. Un if dipende da uno stato che aggiorni tu; Suspense dipende da un render che lancia la promessa.

### Posso mettere Suspense dentro una lista?

Sì, ma un boundary per riga produce molti fallback. Conviene un boundary intorno alla lista e skeleton di riga dentro il fallback.

### Suspense sostituisce un error boundary?

No. Suspense gestisce l'attesa e l'error boundary gestisce l'errore: servono entrambi, con il boundary sopra il Suspense.
