Fetching with loading and error states
🏠The everyday picture
A good waiter says "your food is being prepared", or "sorry, we're out of that, may I suggest…". They never just disappear, leaving you staring at an empty table.
📘What it really is
- Every fetch has three states, and the screen must show each:
- loading: a spinner or skeleton ("Loading enquiries…");
- error: a clear message and a Try again button;
-
success: the data, including the empty case (Module 32, Lesson 5).
-
TanStack Query manages this for you:
npm install @tanstack/react-query
const queryClient = new QueryClient();
<QueryClientProvider client={queryClient}><App /></QueryClientProvider>
const { data, isPending, isError, error, refetch } = useQuery({
queryKey: ["enquiries"],
queryFn: getEnquiries,
});
if (isPending) return <p role="status">Loading enquiries…</p>;
if (isError) return <ErrorMessage message={error.message} onRetry={refetch} />;
return <EnquiryList enquiries={data} />;
-
The query key names the data. Components asking for
["enquiries"]share one cached copy, and if they appear at the same time while the data is loading, they share that one request too. Later, the cache's settings decide whether a new request goes out (Lesson 4 coversstaleTime). Include parameters in the key:["enquiry", id]. -
It also retries failed requests, refreshes data when you return to the tab, and avoids the effect bugs from Module 34.
🖱️Try it
Install TanStack Query. Replace your reducer's starting data with useQuery for the dashboard and for the detail
page (["enquiry", id]). Stop json-server and reload, to see your error state, then start it again and press
Try again. In developer tools, set the network to "Slow 4G" to see the loading state.
✅Quick check
What three states should every screen that fetches data handle?
Show the answer
Loading, error (with a way to retry) and success (including empty).
Two components both use useQuery({ queryKey: ["enquiries"] ... }). How many requests are made?
Show the answer
One. They share the same cached data.
