📖 Notes LESSON 17 OF 18

React Query — Server State

⏱️ 28 min
⚛️ React

Stop Managing Loading States by Hand

React Query handles fetching, caching, and re-fetching server data automatically — replacing the manual useState/useEffect/loading-flag pattern you'd otherwise write for every API call.

useQuery and useMutation

📥
useQuery
Fetches and automatically handles loading, error, and caching states.
⏱️
staleTime
Controls how long cached data is considered "fresh" before refetching.
✏️
useMutation
For create/update/delete operations.
🔄
invalidateQueries
Tells React Query to refetch affected data after a change.
Fetching and Mutating with React Query
JSX
import { useQuery, useMutation, QueryClient } from "@tanstack/react-query";

function Courses() {
  const { data, isLoading } = useQuery({
    queryKey: ["courses"],
    queryFn:  () => fetch("/api/courses").then(r => r.json()),
    staleTime: 5 * 60 * 1000,
  });

  const enroll = useMutation({
    mutationFn: id => fetch(`/api/enroll/${id}`, { method:"POST" }),
    onSuccess: () => queryClient.invalidateQueries(["courses"]),
  });

  if (isLoading) return <Spinner />;
  return data.map(c => <CourseCard key={c.id} onEnroll={() => enroll.mutate(c.id)} {...c} />);
}
Why this replaces useEffect fetching
Removes the repetitive isLoading/error/data boilerplate from every component that talks to an API — caching and refetch logic are handled for you.
🗒 Cheat Sheet 📝 Worksheet