Data Fetching

The code that goes and gets remote data for a screen, plus the loading, error, and stale states that come with the trip.

loadergetting the data for the pagecalling the API for this screenload the data before it showswhere do I put the fetchhooking it up to the backendpulling in the dataapi call for the page

See it

Live demo coming soon

What it is

A fetch is a trip over the network that can be slow, fail, or arrive after the user has moved on. Data fetching is deciding where that trip happens (server or browser), when it starts (before render, during render, on interaction), and what the screen shows for each outcome. Server side that means a route loader, a server component that just awaits, or a build-time fetch. Client side it means TanStack Query, SWR, RTK Query, or a bare fetch inside an effect.

Fetch on the server when you can: the HTML arrives already populated, credentials stay off the client, and you ship less JavaScript. Fetch on the client for anything that changes after load, like search-as-you-type, polling, infinite lists, and filters driven by user input.

The classic trap is the request waterfall: nested components that each fetch their own data serialize the trips, so the page costs the whole chain end to end instead of the single slowest request. Hoist fetches, start independent ones in parallel, and never put a fetch in a component that only renders once its parent's data lands. The other trap: a raw fetch in useEffect has no cache, no dedupe, no retry, and no protection against a stale response landing last. That gap is the entire reason query libraries exist.

Ask AI for it

Implement data fetching for this screen using the framework already in this repository, not a new one. Fetch the route's initial data on the server with whatever mechanism this project uses (route loader, async server component, build-time fetch) so the HTML arrives populated, and pass it down as props. Use TanStack Query only for data that changes through client interaction: search, pagination, refresh, polling, infinite lists. Where the server and the client both touch the same resource, seed the query with the server result instead of fetching it twice, so ownership of that request is unambiguous. Give every query a stable key, choose a staleTime and justify the number in a comment, and pass the query's abort signal into fetch so a stale response cannot land on top of a fresh one. Start independent requests in parallel with Promise.all rather than awaiting them in sequence. Render explicit loading, error with a retry action, and empty states, not just the happy path.

You might have meant

client side data cacheside effectserver side renderingstreaming renderingoptimistic ui

Go deeper