Data ophalen in React en Next.js, vergeleken in één app
Data ophalen in React: server, TanStack Query, SWR | We.Inc
Kies met een korte quiz een manier om data op te halen in React, en vergelijk daarna server components, TanStack Query en SWR op caching, mutaties en standaardinstellingen, in één voorbeeldapp.
Haal data op de server op wanneer dat kan: in de Next.js App Router wacht een async server component op de data voordat er HTML wordt verstuurd, zonder code voor een laadspinner. Voor data die verandert terwijl de pagina open is, gebruikt u een clientcache zoals TanStack Query of SWR, die caching, nieuwe pogingen en mutaties afhandelen. Een kale fetch in useEffect volstaat voor losse verzoeken.
Welke aanpak past
Aanpak
Draait waar
Caching
Het beste voor
Async server component
Server
Standaard niet gecachet; zet het aan met use cache
Paginadata, geheimen, databasequery's
TanStack Query
Browser
Querycache op basis van queryKey
Dashboards, mutaties, paginering
SWR
Browser
Cache op basis van de request key
Weergaven met veel lezen die actueel moeten blijven
useEffect + fetch
Browser
Geen, tenzij u het zelf schrijft
Eén klein verzoek in een kleine app
Elk voorbeeld op deze pagina laadt en bewerkt dezelfde kleine lijst met notities, zodat de verschillen voortkomen uit de aanpak en niet uit de demo. Beantwoord de drie vragen hieronder voor een eerste aanbeveling en het bijpassende codefragment.
Geef aan of u een framework met server components gebruikt, zoals de Next.js App Router.
Geef aan of de data actueel moet blijven terwijl de pagina open is, en of gebruikers de data bewerken.
Lees de aanbeveling en kopieer het bijpassende fragment.
Gebruik de vergelijkingen hieronder om de standaardinstellingen te controleren voordat u live gaat.
Start verzoeken tegelijk. Twee awaits achter elkaar vormen een waterval; maak eerst beide promises aan en gebruik dan await Promise.all.
Geef elke useQuery die dezelfde data leest dezelfde queryKey, zodat componenten één verzoek en één cache-item delen.
Invalideer na een mutatie de betreffende key in plaats van de cache met de hand aan te passen, tenzij u een directe optimistische update nodig hebt.
Haal nooit geheimen op in een client component. Alles wat de browser opvraagt, kunnen mensen zien in het netwerkpaneel.
Veelgestelde vragen
Worden fetch-verzoeken gecachet in de Next.js App Router?
Volgens de huidige Next.js-documentatie worden fetch-verzoeken standaard niet gecachet en blokkeren ze het renderen tot ze klaar zijn. Identieke verzoeken binnen één render worden gememoïseerd, en u kiest voor caching met de use cache-directive of streamt verse data binnen Suspense.
Wat zijn de belangrijke standaardinstellingen van TanStack Query?
Data is direct verouderd (staleTime 0), dus wordt opnieuw opgehaald bij mount, vensterfocus en herverbinding. Ongebruikte query's blijven 5 minuten in het geheugen (gcTime), en mislukte query's worden 3 keer opnieuw geprobeerd met exponentiële backoff. Verhoog staleTime als dat opnieuw ophalen meer is dan u nodig hebt.
TanStack Query of SWR?
Beide cachen op key en valideren opnieuw bij focus en herverbinding. TanStack Query heeft meer ingebouwde functies voor mutaties, invalidatie en devtools; SWR heeft een kleinere API rond useSWR(key, fetcher). Kies er één per app; beide gebruiken verdubbelt de cache.
Heb ik met server components nog een clientbibliotheek nodig?
Voor het laden van pagina's vaak niet. U hebt er een nodig wanneer data moet verversen zonder navigatie, wanneer gebruikers bewerken en directe feedback verwachten, of voor oneindige lijsten. Veel apps laden op de server en gebruiken alleen op interactieve schermen een clientcache.
Hoe controleer ik op de server wie er met Supabase is ingelogd?
De server-side gids van Supabase zegt dat u getSession() nooit moet vertrouwen in servercode. Roep supabase.auth.getClaims() aan, dat de handtekening van het token verifieert, en voer dan query's uit op uw tabellen; row level security blijft voor elke query gelden.
Eerst de server, daarna een clientcache waar nodig
Een server component kan direct een database bevragen of een API aanroepen met inloggegevens, en het resultaat komt aan als HTML. Dat haalt code voor laadstatussen uit de meeste pagina's en houdt sleutels buiten de browserbundle.
Interactieve schermen zijn anders. Een notitielijst waar mensen iets aan toevoegen, op filteren en naar terugkeren, heeft baat bij een clientcache die resultaten tussen schermen onthoudt en ze op de achtergrond ververst.
Streamen in plaats van wachten
Als één verzoek traag is, zet de component die het nodig heeft dan in Suspense met een fallback. De rest van de pagina wordt meteen verstuurd en het trage deel streamt later binnen. Een loading.js-bestand doet hetzelfde voor een heel routesegment in Next.js.
In een client component kunt u ook een promise van de server ontvangen en die lezen met de use-API van React binnen Suspense.
Waarom het simpele useEffect-patroon tekortschiet
Een fetch in useEffect heeft geen cache, dus elke mount herhaalt het verzoek, en race conditions, laden en fouten moet u met de hand afhandelen. Voor één kleine widget is dat prima. Voor alles wat groter is, geeft een bibliotheek u dat allemaal in een paar regels; de basis van fetch zelf staat in onze gids over async en fetch.
Standaardinstellingen die mensen verrassen
Gedrag zonder extra configuratie
Gedrag
Next.js server fetch
TanStack Query
SWR
Gecachet over verzoeken heen
Nee, zet het aan met use cache
In het geheugen, per browsertabblad
In het geheugen, per browsertabblad
Dubbele verzoeken
Gememoïseerd binnen één render
Gedeeld via queryKey
Ontdubbeld per key binnen 2 seconden
Opnieuw ophalen bij vensterfocus
Niet van toepassing
Ja, als de data verouderd is
Ja
Opnieuw ophalen bij herverbinding
Niet van toepassing
Ja, als de data verouderd is
Ja
Nieuwe pogingen bij fouten
Zelf afhandelen
3, met exponentiële backoff
Ja (errorRetryInterval 5000 ms)
Ongebruikte data bewaard voor
Niet van toepassing
5 minuten (gcTime)
Geen gedocumenteerde standaard
Watervallen op de server voorkomen
Start beide verzoeken en wacht er dan samen op
Door beide functies aan te roepen voordat u await gebruikt, wacht geen van beide op de ander.
Stream een traag deel met Suspense
De kop wordt meteen verstuurd; de notitielijst streamt binnen zodra de data er is.
Supabase in een server component
Dit gebruikt de createClient-helper uit de Next.js server-side gids van Supabase (lib/supabase/server.ts, gebouwd op @supabase/ssr). getClaims() verifieert het token van de ingelogde gebruiker voordat de query draait.
Notities van de ingelogde gebruiker, geladen op de server
Row level security op de tabel notes bepaalt welke rijen terugkomen.
Kies een aanpak
Gebruikt u server components (bijvoorbeeld de Next.js App Router)?
Moet de data verversen terwijl de pagina open blijft?
Bewerken gebruikers deze data op het scherm?
Ja
Nee
Startfragment
Fragment kopiëren
Laad het in een async server component. Voeg later alleen een clientcache toe voor de delen die interactief worden.
Gebruik TanStack Query: useQuery om te lezen, useMutation om te schrijven, en invalidateQueries om na een wijziging te verversen.
Gebruik SWR: useSWR houdt de weergave actueel bij focus en herverbinding, met heel weinig code.
Eén fetch in useEffect is hier genoeg. Ruim op met een ignore-vlag zodat een laat antwoord geen nieuwere state kan overschrijven.