Client Data Fetching
Master client-side data fetching in Next.js with SWR and TanStack Query — when to use it, how to combine it with Server Components, and production patterns.
Last reviewed: January 2025
🔍 What Is It?
Client data fetching runs in the browser after the page loads. Use it for:
- →Real-time data — live notifications, stock prices, chat messages
- →User-triggered fetches — search results as user types, load more on scroll
- →Optimistic updates — update UI immediately, sync with server in background
- →Polling — refresh data every N seconds without navigation
The right tools:
- →SWR (by Vercel) — lightweight, excellent for simple cases
- →TanStack Query (React Query) — more powerful, better for complex mutation flows
- →Never raw
useEffect + fetch— no caching, no deduplication, no revalidation
🎯 Why Do We Need It?
Server Components handle most data fetching in Next.js, but some data genuinely belongs on the client:
- →Data that changes in real-time without user navigation
- →Data that depends on browser state (geolocation, device info)
- →Infinite scroll / load more patterns
- →Optimistic UI (update before server confirms)
- →Data that should refresh on window focus (SWR's killer feature)
🏗️ What Happens in Real Projects?
Client fetching in a SaaS dashboard:
- →Notifications bell — SWR with
refreshInterval: 30000(poll every 30s) - →Search — TanStack Query with debounced query key
- →User profile — SWR with
revalidateOnFocus: true - →Live order status — SWR with short polling or WebSocket
- →Infinite feed — TanStack Query
useInfiniteQuery
⚙️ How It Works
SWR flow:
- Component mounts — SWR checks cache for the key
- If cached: returns cached data immediately (stale)
- Triggers background revalidation (fetches fresh data)
- Updates component with fresh data if changed (stale-while-revalidate)
TanStack Query flow:
Same stale-while-revalidate model with additional features: mutations with rollback, query invalidation, background refetching, and a DevTools panel.
💻 Example
SWR and TanStack Query Patterns — Real client-side data fetching patterns used in production Next.js apps.
🤔 Common Confusions
❓ Should I use SWR or TanStack Query?
SWR for simple read-heavy cases (notifications, user profile, dashboard stats). TanStack Query for complex mutation flows, optimistic updates, infinite scroll, or when you need the DevTools for debugging. Both are excellent — pick one and be consistent.
❓ Can I use client data fetching alongside Server Components?
Yes — this is the standard pattern. Server Components handle the initial data load (fast, SSR). Client Components use SWR/TanStack Query for real-time updates and mutations. You can even pre-populate the SWR cache with server-fetched data using fallbackData.
❓ Why not just use useEffect + fetch?
useEffect + fetch has no caching, no deduplication, no revalidation, no error retry, and creates race conditions on fast re-renders. SWR and TanStack Query solve all of these. The only reason to use raw fetch in a Client Component is for one-off mutations (form submits) where you do not need the response cached.
🚨 Common Production Issues
SWR cache not invalidated after mutations — after a POST/PUT/DELETE, call mutate(key) to tell SWR to revalidate. Otherwise users see stale data after their action.
Waterfall from client fetching — if your page shell is a Server Component but critical data is client-fetched, users see a loading spinner on first load. Pre-fetch on the server and pass as initialData/fallbackData to SWR.
Too many polling intervals — 10 components each polling every 30 seconds = 10 requests every 30 seconds. Lift polling to a shared context or use a single SWR call and share the data via context.
✅ Best Practices
Pre-populate SWR/TanStack Query cache with server-fetched data to avoid client-side loading flash
Use a shared fetcher function with error handling instead of inline fetch calls
Set up a global QueryClient with sensible defaults (staleTime, retry) rather than configuring per query
Use optimistic updates for mutations that users expect to be instant (like/unlike, add to cart)
Deduplicate polling by lifting shared data to a context provider
🏛️ Architect's Note
The Server/Client data fetching split maps cleanly to a read/write architecture. Server Components handle reads (fetch and render data). Client Components handle writes (mutations) and real-time updates. This separation keeps Server Components pure and testable while giving Client Components the reactivity they need.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
↗ Where this topic fits
Next.js Technology Guide
Return to the Next.js learning hub.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Sources
Sources / References
Use these Next.js references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide Next.js learning path
Browse the full Next.js topic collection and learning order on SplashRide.
Next.js Interview Prep
Practice Next.js interview questions and scenario-based answers.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Next.js Server Data Fetching: Async Server Components and Caching
Learn Next.js server data fetching with async Server Components, parallel and sequential requests, direct database access, caching, loading, and error handling.
Route Handlers
Master Route Handlers in Next.js — the App Router replacement for API routes, supporting all HTTP methods, streaming responses, and edge runtime.