Data fetching in React e Next.js, a confronto su un'unica app
Data fetching in React: server, TanStack Query, SWR | We.Inc
Scegli un approccio al data fetching in React con un breve quiz, poi confronta server component, TanStack Query e SWR su cache, mutation e comportamenti predefiniti, su un'unica app di esempio.
Recupera i dati sul server quando puoi: nell'App Router di Next.js un server component asincrono attende i dati prima che venga inviato qualsiasi HTML, senza codice per lo spinner di caricamento. Per i dati che cambiano mentre la pagina è aperta, usa una cache lato client come TanStack Query o SWR, che gestiscono cache, nuovi tentativi e mutation. Un semplice fetch in useEffect va bene per richieste occasionali.
Quale approccio si adatta
Approccio
Dove viene eseguito
Cache
Ideale per
Server component asincrono
Server
Nessuna cache predefinita; attivala con use cache
Dati della pagina, segreti, query al database
TanStack Query
Browser
Cache delle query indicizzata per queryKey
Dashboard, mutation, paginazione
SWR
Browser
Cache indicizzata per la chiave della richiesta
Viste con molte letture che devono restare aggiornate
useEffect + fetch
Browser
Nessuna, a meno che tu non la scriva
Una piccola richiesta in una piccola app
Ogni esempio in questa pagina carica e modifica la stessa piccola lista di note, quindi le differenze dipendono dall'approccio e non dalla demo. Rispondi alle tre domande qui sotto per avere una raccomandazione di partenza e lo snippet corrispondente.
Indica se usi un framework con server component, come l'App Router di Next.js.
Indica se i dati devono restare aggiornati mentre la pagina è aperta, e se gli utenti li modificano.
Leggi la raccomandazione e copia lo snippet corrispondente.
Usa le sezioni di confronto qui sotto per controllare i comportamenti predefiniti prima di pubblicare.
Avvia le richieste insieme. Due await di fila formano una cascata; crea prima entrambe le promise e poi fai await di Promise.all.
Usa la stessa queryKey in ogni useQuery che legge gli stessi dati, così i componenti condividono una richiesta e una voce di cache.
Dopo una mutation, invalida la chiave interessata invece di modificare la cache a mano, a meno che non ti serva un aggiornamento ottimistico istantaneo.
Non recuperare mai segreti in un client component. Tutto ciò che il browser richiede è visibile a chiunque nel pannello di rete.
Domande frequenti
Le richieste fetch sono in cache nell'App Router di Next.js?
Secondo l'attuale documentazione di Next.js, le richieste fetch non sono in cache per impostazione predefinita e bloccano il rendering finché non terminano. Le richieste identiche in un rendering vengono memoizzate, e attivi la cache con la direttiva use cache oppure trasmetti dati freschi in streaming dentro Suspense.
Quali sono i default importanti di TanStack Query?
I dati diventano subito obsoleti (staleTime 0), quindi vengono ricaricati al mount, al focus della finestra e alla riconnessione. Le query inutilizzate restano in memoria per 5 minuti (gcTime), e le query fallite riprovano 3 volte con backoff esponenziale. Aumenta staleTime se questi ricaricamenti sono più di quanto ti serve.
TanStack Query o SWR?
Entrambi fanno cache per chiave e rivalidano al focus e alla riconnessione. TanStack Query include più funzioni integrate per mutation, invalidazione e devtools; SWR ha un'API più piccola costruita attorno a useSWR(key, fetcher). Scegline uno per app; usarli entrambi duplica la cache.
Mi serve ancora una libreria client con i server component?
Spesso no per il caricamento delle pagine. Ti serve quando i dati devono aggiornarsi senza navigazione, quando gli utenti modificano e si aspettano un riscontro immediato, o per le liste infinite. Molte app caricano sul server e usano una cache client solo nelle schermate interattive.
Come dovrei verificare chi ha effettuato l'accesso con Supabase sul server?
La guida lato server di Supabase dice di non fidarsi mai di getSession() nel codice server. Chiama supabase.auth.getClaims(), che verifica la firma del token, poi interroga le tue tabelle; la row level security si applica comunque a ogni query.
Prima il server, poi aggiungi una cache client dove serve
Un server component può interrogare un database o chiamare un'API con le credenziali direttamente, e il risultato arriva come HTML. Questo elimina il codice per lo stato di caricamento dalla maggior parte delle pagine e tiene le chiavi fuori dal bundle del browser.
Le schermate interattive sono diverse. Una lista di note a cui le persone aggiungono elementi, che filtrano e su cui tornano trae vantaggio da una cache client che ricorda i risultati tra le schermate e li aggiorna in background.
Streaming invece di attendere
Se una richiesta è lenta, avvolgi il componente che ne ha bisogno in Suspense con un fallback. Il resto della pagina viene inviato subito e la parte lenta arriva in streaming. Un file loading.js fa lo stesso per un intero segmento di route in Next.js.
In un client component puoi anche ricevere una promise dal server e leggerla con l'API use di React dentro Suspense.
Perché il semplice schema con useEffect non basta
Un fetch in useEffect non ha cache, quindi ogni mount ripete la richiesta, e richiede la gestione manuale di race condition, caricamento ed errori. Va bene per un piccolo widget. Per qualsiasi cosa più grande, una libreria ti dà tutto questo in poche righe; le basi di fetch sono trattate nella nostra guida su async e fetch.
Default che sorprendono
Comportamento predefinito
Comportamento
Fetch lato server in Next.js
TanStack Query
SWR
In cache tra le richieste
No, attivala con use cache
In memoria, per scheda del browser
In memoria, per scheda del browser
Richieste duplicate
Memoizzate in un singolo rendering
Condivise per queryKey
Deduplicate per chiave entro 2 secondi
Ricarica al focus della finestra
Non applicabile
Sì, quando obsoleti
Sì
Ricarica alla riconnessione
Non applicabile
Sì, quando obsoleti
Sì
Nuovi tentativi in caso di errore
Gestiscili tu
3, con backoff esponenziale
Sì (errorRetryInterval 5000 ms)
Dati inutilizzati conservati per
Non applicabile
5 minuti (gcTime)
Non è un default documentato
Evitare le cascate sul server
Avvia entrambe le richieste, poi attendile insieme
Chiamare entrambe le funzioni prima dell'await significa che nessuna aspetta l'altra.
Trasmetti in streaming una parte lenta con Suspense
Il titolo viene inviato subito; la lista di note arriva in streaming quando arrivano i suoi dati.
Supabase in un server component
Qui si usa l'helper createClient dalla guida lato server di Supabase per Next.js (lib/supabase/server.ts, basato su @supabase/ssr). getClaims() verifica il token dell'utente connesso prima che la query venga eseguita.
Note dell'utente connesso, caricate sul server
La row level security sulla tabella notes decide quali righe vengono restituite.
Scegli un approccio
Usi i server component (per esempio l'App Router di Next.js)?
I dati devono aggiornarsi mentre la pagina resta aperta?
Gli utenti modificano questi dati sullo schermo?
Sì
No
Snippet di partenza
Copia snippet
Caricali in un server component asincrono. Aggiungi una cache client in seguito solo per le parti che diventano interattive.
Usa TanStack Query: useQuery per leggere, useMutation per scrivere e invalidateQueries per aggiornare dopo una modifica.
Usa SWR: useSWR mantiene la vista aggiornata al focus e alla riconnessione con pochissimo codice.
Qui basta un singolo fetch in useEffect. Fai pulizia con un flag ignore così una risposta tardiva non può sovrascrivere uno stato più recente.