Tanstack Query is a JavaScript library designed to simplify the complex task of data fetching and caching in React applications.
Introduction
Tanstack Query is a powerful library developed by TanStack that simplifies data fetching and state management in React applications. It provides a straightforward way to manage remote data and keep it in sync with the UI.
What is Tanstack Query?
Tanstack Query is a JavaScript library designed to simplify the complex task of data fetching and caching in React applications. It offers a set of hooks and utilities that enable you to manage data from various sources, including REST APIs, GraphQL, or even local state, effortlessly.
Why Choose Tanstack Query Over Other Libraries?
Many developers traditionally use Redux, Axios, or React’s built-in useState and useEffect for managing API requests. However, Tanstack Query provides several advantages:
- Automatic Caching: Built-in caching reduces unnecessary network requests.
- Background Synchronization: Ensures your data is always up-to-date.
- Pagination & Infinite Scrolling: Simplifies data handling for large datasets.
- Optimistic Updates: Provides a smoother UX with near-instantaneous responses.
- Error & Loading State Management: Handles these states without extra boilerplate.
- Simplified Data Fetching: Hooks-based API reduces complexity compared to Redux Thunk/Saga.
Key Features
- Declarative Data Fetching: Define queries and mutations using hooks like
useQueryanduseMutation. - Automatic Caching & Background Updates: Tanstack Query caches data and keeps it updated in the background.
- Pagination & Infinite Queries: Simplifies managing large datasets.
- Optimistic Updates: Provides instant UI updates before receiving API responses.
Getting Started with Tanstack Query
Installation
npm install @tanstack/react-query
Setting up Query Client Provider
Create a QueryClient and wrap your app with QueryClientProvider.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
Fetching Data with useQuery
Fetching user data from an API using Tanstack Query:
import { useQuery } from '@tanstack/react-query';
const fetchUsers = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
return response.json();
};
export default function Users() {
const { data, error, isLoading, refetch } = useQuery(['users'], fetchUsers, {
enabled: false, // Prevents auto-fetching
});
return (
<div>
<button onClick={() => refetch()}>Get Users</button>
{isLoading && <p>Loading...</p>}
{error && <p>Error fetching data</p>}
{data && data.map((user) => <p key={user.id}>{user.name}</p>)}
</div>
);
}
Mutating Data with useMutation
Performing a POST request with useMutation:
import { useMutation } from '@tanstack/react-query';
const createPost = async (newPost) => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify(newPost),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
return response.json();
};
export default function CreatePost() {
const { mutate, isLoading, data } = useMutation(createPost);
return (
<div>
<button
onClick={() =>
mutate({ title: 'New Post', body: 'Post Content', userId: 1 })
}
>
Add Post
</button>
{isLoading && <p>Adding post...</p>}
{data && <p>Post added: {data.title}</p>}
</div>
);
}
Tanstack Query Use Cases
- Fetching & Caching API Data: Auto-caches and re-fetches data for APIs.
- Optimistic Updates: Provides an instant UI update before API response.
- Background Syncing: Keeps data fresh without manual fetching.
- Pagination & Infinite Scrolling: Handles large datasets efficiently.
Comparing useQuery vs useMutation
| Feature | useQuery | useMutation |
|---|---|---|
| Purpose | Fetching data | Mutating data |
| API Calls | GET requests | POST, PUT, DELETE requests |
| Auto-fetching | Yes | No (manually triggered) |
| Data Caching | Yes | No |
| Error Handling | Yes | Yes (optimistic updates supported) |
Handling Infinite Queries
Example of implementing infinite scrolling:
import { useInfiniteQuery } from '@tanstack/react-query';
const fetchPosts = async ({ pageParam = 1 }) => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts?_page=${pageParam}`
);
return response.json();
};
export default function InfinitePosts() {
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery(
['posts'],
fetchPosts,
{ getNextPageParam: (lastPage, pages) => pages.length + 1 }
);
return (
<div>
{data?.pages.map((page) =>
page.map((post) => <p key={post.id}>{post.title}</p>)
)}
{hasNextPage && (
<button onClick={() => fetchNextPage()}>Load More</button>
)}
</div>
);
}
Conclusion
Tanstack Query is a valuable addition to the React ecosystem, making data fetching and synchronization easier than ever. Whether you’re building a small application or a large-scale project, Tanstack Query’s simplicity and powerful features will help you manage your data effectively.
By simplifying data management, Tanstack Query allows you to focus on building your application’s features and providing a better user experience. Give it a try in your next React project, and you’ll likely wonder how you managed data without it.
For more detailed information, check out the official TanStack Query documentation.
Continue Reading