Data Fetching and Server State: Complete Guide
Data fetching and server state management is the bridge between your React components and backend APIs. This chapter teaches you how to manage server data at scale: caching responses, syncing mutations, paginating results, and handling real-time updates—all without the boilerplate. You'll learn three production-grade patterns (TanStack Query, SWR, RTK Query) and solve the problems they solve: race conditions, stale cache, duplicate requests, and failed retries.
Key Takeaways
- Server state is distinct from UI state and requires dedicated management tools, not Redux or Context.
- TanStack Query automates caching, synchronization, and invalidation so you never display stale data.
- Optimistic updates and mutation queues let you handle failures gracefully while keeping the UI responsive.
- Pagination and infinite scroll patterns can be implemented with a few hooks; prefetching eliminates loading states.
- WebSockets and Server-Sent Events (SSE) enable real-time data push for collaborative and live-feed apps.
What This Chapter Covers
This chapter is organized into five practical series that build on each other:
TanStack Query Essentials
Learn the core concept: React Query (now TanStack Query) is a server-state library that abstracts away the complexity of async request handling. You'll set up a query client, fetch data with useQuery and useInfiniteQuery, and understand the caching lifecycle. By the end of this series, you'll never write a custom useState + useEffect data-fetching loop again.
Mutations, Invalidation, and Optimistic UI
Server state isn't read-only. You'll master mutations with useMutation, background refetching, query invalidation to keep your cache fresh, and optimistic updates that show changes immediately while the request completes. Learn how to roll back failed mutations and queue updates for offline-first apps.
Pagination, Infinite Scroll, and Prefetching
Real apps fetch large datasets. This series covers paginated queries with predictable URLs, infinite-scroll patterns that load "next page" on demand, and prefetching strategies that load the next page before the user scrolls down. You'll reduce perceived latency and build snappy UIs.
SWR and RTK Query in Practice
TanStack Query isn't the only option. You'll compare SWR (Vercel's lightweight client) and RTK Query (Redux Toolkit's server-state layer). Learn when each shines, how they differ in API design, and how to migrate between them without rewriting your code.
Real-Time Data With WebSockets and SSE
Live updates transform user experience. This series teaches you to push data from server to browser using WebSockets (bidirectional) and Server-Sent Events (unidirectional). You'll integrate real-time data into TanStack Query, handle connection lifecycle, and rebuild cache on reconnect.
What You'll Learn
- Set up and configure TanStack Query, SWR, and RTK Query in a React app
- Fetch data efficiently with caching, deduplication, and smart background refetching
- Mutate server data with optimistic updates, rollbacks, and error handling
- Implement pagination, infinite scroll, and prefetching to maximize UX
- Build real-time features with WebSockets and Server-Sent Events
- Debug server-state bugs with DevTools and logging
- Migrate from a custom data-fetching layer to a production library
Who This Chapter Is For
This chapter assumes you know React hooks (useState, useEffect, useContext), async/await, and can read a REST API. You should have built at least one component that fetches data. If you're tired of managing loading/error/data states manually, or you're asking "why does my mutation cause a stale GET?", this chapter is for you.
After this chapter, you'll be able to:
- Build a production app that fetches, caches, and mutates server data without Redux or custom boilerplate
- Debug why mutations fail and how to recover gracefully
- Design an app architecture that separates server state from UI state, making it easier to reason about data flow
- Implement real-time features that sync across browser tabs and recover after network loss
- Choose the right server-state library for your next project and migrate if needed
Frequently Asked Questions
Why do I need a server-state library instead of useState + useEffect?
Server state has unique challenges: it lives on the server, changes without your app knowing, expires after time, and requires deduplication (two components fetching the same data should share the request). Libraries like TanStack Query handle retries, background sync, cache invalidation, and race conditions automatically. Using useState alone means you'll reinvent these solutions each time.
What's the difference between server state and UI state?
Server state is data from an API—a user profile, a list of posts, a comment. It's shared across your app, can become stale, and might fail to fetch. UI state is local—whether a modal is open, a form input value, the scroll position. Use TanStack Query for server state and useState for UI state. Mixing them causes bugs.
Can I use TanStack Query with GraphQL?
Yes. TanStack Query works with GraphQL queries, mutations, and subscriptions. The library doesn't care how you fetch; it manages the cache based on keys you define. You'll use Apollo Client or Urql (which have their own caching) or pair TanStack Query with a raw GraphQL fetch. This chapter focuses on REST, but patterns apply to GraphQL.