Why Is useEffect for Data a Mistake?
At the start, everyone uses useEffect for loading data. But as soon as the application grows, problems begin:
- How to cache data so it's not loaded on every click?
- What if two components request the same list simultaneously? (extra requests)
- How to update data if it changed on the server?
TanStack Query (formerly React Query) solves all these problems at once.
1. The Concept of " Server State "
You need to clearly separate data:
- Client State: What lives only in the browser (is menu open, text in field).
- Server State: Data that doesn't belong to you. It's in the database, and you just " rent " it for display.
2. Analogy: Smart Librarian
Imagine React Query is a librarian.
- You ask for a book (data).
- The librarian gives it to you. But they remember: " So, this book was already borrowed " .
- If a minute later someone else asks for the same book, the librarian won't go to the warehouse. They'll just give the copy they already have at hand (Cache).
- At the same time, they check once a day if a new edition of this book came out (Background refetching).
3. How Does It Look in Code?
import { useQuery } from '@tanstack/react-query';
function UsersList() {
const { data, isLoading, isError } = useQuery({
queryKey: ['users'], // Unique key (address in cache)
queryFn: fetchUsers, // Loader function
});
if (isLoading) return <span>Loading...</span>;
if (isError) return <span>Error :(</span>;
return (
<ul>
{data.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
4. Main Advantages:
- Auto-caching: User pressed " Back " — data appeared instantly, without waiting.
- Deduplication: If 10 components on the page request a user list, only one network request will be sent.
- Indicators: The library tells you if loading is happening (
isLoading) and if there's an error (isError). You no longer need to create these states manually!
TanStack Query is the industry standard. It turns working with API from pain to pleasure.