Mastering Data Fetching with React Query
🚀 **Overview**: React Query (TanStack Query) is one of the most impactful libraries for managing server-state in React apps. It handles caching, background updates, persistency, pagination, retries, and automatic UI synchronization. If you're tired of managing loading states, global state, or manual API calls—React Query is your best friend.
📌 **Why Use React Query?**
- Eliminates manual API state management - Built-in caching & deduplication - Background refetching for fresh data - Auto retry on failed requests - Pagination & infinite queries support - Avoids unnecessary global state libraries - Makes API calls predictable and declarative
1️⃣ **Setup React Query in a React/Next.js App**
1import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2
3const queryClient = new QueryClient();
4
5export default function App() {
6 return (
7 <QueryClientProvider client={queryClient}>
8 <YourComponents />
9 </QueryClientProvider>
10 );
11}2️⃣ **Basic Data Fetching with useQuery**
The `useQuery` hook handles fetching, caching, and updating data automatically with zero boilerplate.
1const { data, isLoading, error } = useQuery({
2 queryKey: ["users"],
3 queryFn: () => axios.get("/api/users").then(res => res.data),
4});
5
6if (isLoading) return <p>Loading...</p>;
7if (error) return <p>Error fetching users</p>;📍 **What is queryKey?**
`queryKey` uniquely identifies the query. React Query caches data by this key and smartly decides when to refetch.
3️⃣ **Mutations with useMutation (Create, Update, Delete)**
`useMutation` is used for POST, PUT, PATCH, DELETE operations. It does not automatically refetch data — so we invalidate queries manually.
1const mutation = useMutation({
2 mutationFn: (newUser) => axios.post("/api/users", newUser),
3 onSuccess: () => {
4 queryClient.invalidateQueries(["users"]);
5 },
6});📌 **Why Invalidate Queries?**
- Ensures UI shows fresh data - No need to manually update lists - Maintains consistency automatically
4️⃣ **Handling Pagination with Query Keys**
1const { data } = useQuery({
2 queryKey: ["users", page],
3 queryFn: () => axios.get(`/api/users?page=${page}`).then(res => res.data),
4});5️⃣ **Infinite Queries (Infinite Scroll)**
1const {
2 data,
3 fetchNextPage,
4 hasNextPage,
5} = useInfiniteQuery({
6 queryKey: ["posts"],
7 queryFn: ({ pageParam = 1 }) =>
8 axios.get(`/api/posts?page=${pageParam}`).then(res => res.data),
9 getNextPageParam: (lastPage) => lastPage.nextPage,
10});6️⃣ **Prefetching Data for Faster UI Navigation**
1queryClient.prefetchQuery({
2 queryKey: ["users"],
3 queryFn: () => axios.get("/api/users").then(res => res.data),
4});7️⃣ **Background Refetching for Fresh Data**
React Query automatically refetches data when:
- Browser window is refocused - Network reconnects - Stale time expires
1const { data } = useQuery({
2 queryKey: ["users"],
3 queryFn: fetchUsers,
4 staleTime: 1000 * 60, // 1 minute
5});8️⃣ **React Query DevTools for Debugging**
1import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
2
3<QueryClientProvider client={queryClient}>
4 <YourApp />
5 <ReactQueryDevtools initialIsOpen={false} />
6</QueryClientProvider>🎯 **Conclusion**: React Query transforms how you handle server state in React. With features like caching, mutation handling, pagination, retries, and automatic background refetching, it removes complexity and improves performance dramatically. Whether you're building dashboards, SaaS apps, or microservice-based web apps — React Query is essential for production-grade React development.
