Data Fetching (React Query & SWR)
5 questions foundWhat problem do libraries like React Query and SWR solve compared to fetching data with plain useEffect?
Beginner Fetching data with plain useEffect means you have to manually handle loading states, errors, caching, and refetching yourself every single time. React Query and SWR handle all of this automatically, and they also cache results so the same data does not need to be fetched again every time a component appears on the screen.
import { useQuery } from '@tanstack/react-query';
function Products() {
const { data, isLoading, error } = useQuery({
queryKey: ['products'],
queryFn: () => fetch('/api/products').then((res) => res.json()),
});
if (isLoading) return <p>Loading</p>;
if (error) return <p>Something went wrong</p>;
return <ProductList items={data} />;
}
Real-world example An online store switches from manually written fetch and useEffect code to React Query, immediately gaining automatic caching so navigating back to a previously visited page shows data instantly instead of showing a loading spinner again.
Common follow-ups: How does React Query decide when cached data has become too old and needs to be refetched?;What is the difference between React Query and SWR at a high level?
Custom Hooks;Effects & Lifecycle
How does automatic caching work in React Query, and why does it make an app feel faster?
Intermediate React Query stores the result of each request under a unique key, and if a component asks for that same key again, it shows the cached data instantly while quietly checking in the background whether the data has changed on the server. This means users often see content immediately instead of waiting for a fresh network request every time.
// Both components share the same cached result automatically
useQuery({ queryKey: ['user', 5], queryFn: () => fetchUser(5) });
// Later, on a different page
useQuery({ queryKey: ['user', 5], queryFn: () => fetchUser(5) }); // instantly returns cached data first
Real-world example A social media app shows a user's profile instantly when navigating back to a previously viewed page, since React Query already had that exact profile data cached from the first visit only moments earlier.
Common follow-ups: How long does React Query keep cached data before considering it too old by default?;How would you manually clear or update a specific piece of cached data?
Performance (memo/useMemo);State Management
How would you handle a mutation, such as creating a new item, using React Query?
Intermediate React Query provides a useMutation hook specifically for actions that change data on the server, like creating, updating, or deleting something. After the mutation succeeds, you can tell React Query to refresh any related cached data so the screen shows the latest information automatically.
import { useMutation, useQueryClient } from '@tanstack/react-query';
function AddProductForm() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: (newProduct) => fetch('/api/products', { method: 'POST', body: JSON.stringify(newProduct) }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['products'] }),
});
return <button onClick={() => mutation.mutate({ name: 'New Item' })}>Add Product</button>;
}
Real-world example An admin panel automatically refreshes its product list the moment a new product is successfully added, since the mutation tells React Query to invalidate and refetch the products list right after the request succeeds.
Common follow-ups: What does invalidating a query actually do behind the scenes?;How would you show a loading spinner specifically while a mutation is in progress?
Server Actions & Data Mutations;Forms: Controlled & Uncontrolled Components
How does SWR's stale while revalidate strategy work, and why is it useful?
Advanced SWR immediately shows any data it already has cached, even if it might be slightly outdated, while quietly fetching a fresh copy in the background at the same time. Once the fresh data arrives, the screen updates automatically. This gives users an instant response instead of a loading spinner, while still keeping the data reasonably up to date.
import useSWR from 'swr';
function Weather() {
const { data } = useSWR('/api/weather', (url) => fetch(url).then((res) => res.json()));
if (!data) return <p>Loading</p>;
return <p>Temperature: {data.temp} degrees</p>;
}
Real-world example A weather app shows yesterday's cached temperature instantly when opened, then quietly updates to today's real temperature a moment later once the background request finishes, using SWR's stale while revalidate approach.
Common follow-ups: What does the name SWR actually stand for, and how does it relate to this behavior?;How would you force SWR to always fetch fresh data and skip showing the stale cache first?
Performance (memo/useMemo);Caching
Why is it usually better to use a data fetching library instead of writing your own fetch logic in every component?
Beginner Writing your own fetch logic in every component means repeating the same loading, error, and caching code over and over, and it is easy to make small mistakes, like forgetting to cancel a request when a component unmounts. A dedicated library like React Query or SWR handles all of these details consistently, tested by thousands of other developers, saving time and reducing bugs.
// Repeated manually in every component, error prone
useEffect(() => {
let cancelled = false;
fetch(url).then((res) => res.json()).then((data) => {
if (!cancelled) setData(data);
});
return () => { cancelled = true; };
}, [url]);
// Handled automatically by a library
const { data } = useQuery({ queryKey: [url], queryFn: () => fetch(url).then((res) => res.json()) });
Real-world example A growing team notices they had written slightly different, occasionally buggy fetch logic in over a dozen different components, and standardizes on React Query to fix the inconsistencies and reduce duplicated code.
Common follow-ups: What specific bugs commonly happen when developers write their own fetch logic by hand?;How steep is the learning curve for adopting a library like React Query in an existing project?
Effects & Lifecycle;Custom Hooks