How to Implement React Query in React
This article provides a practical, step-by-step guide on how to integrate and use React Query (now known as TanStack Query) in a React application. You will learn how to install the package, set up the global query provider, fetch data using queries, and handle data mutations to keep your server state synchronized with your user interface.
Step 1: Install React Query
To get started, install the official TanStack Query package using your preferred package manager. Run one of the following commands in your project terminal:
# Using npm
npm install @tanstack/react-query
# Using yarn
yarn add @tanstack/react-queryStep 2: Configure the QueryClientProvider
React Query requires a QueryClientProvider to wrap your
application and manage the cache. You should set this up at the entry
point of your React application (usually main.jsx or
index.js).
import React from 'react';
import ReactDOM from 'react-dom/client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from './App';
// Create a client instance
const queryClient = new QueryClient();
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</React.StrictMode>
);Step 3: Fetch Data Using
useQuery
To fetch data, use the useQuery hook. This hook requires
a unique queryKey to manage the cache and a
queryFn (an asynchronous function that fetches the
data).
Here is an example of fetching a list of users from a public API:
import { useQuery } from '@tanstack/react-query';
// Asynchronous fetch function
const fetchUsers = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
};
function UserList() {
const { data, error, isLoading, isError } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
});
if (isLoading) {
return <p>Loading users...</p>;
}
if (isError) {
return <p>Error: {error.message}</p>;
}
return (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export default UserList;Step 4: Modify Data Using
useMutation
To create, update, or delete data on the server, use the
useMutation hook. You can combine it with
useQueryClient to invalidate existing queries, forcing
React Query to automatically refetch and display the latest data.
Here is an example of adding a new user:
import { useMutation, useQueryClient } from '@tanstack/react-query';
// Asynchronous mutation function
const createUser = async (newUserData) => {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newUserData),
});
return response.json();
};
function AddUserButton() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: createUser,
onSuccess: () => {
// Invalidate the 'users' cache to trigger a background refetch
queryClient.invalidateQueries({ queryKey: ['users'] });
},
});
const handleAddUser = () => {
mutation.mutate({ name: 'Jane Doe' });
};
return (
<div>
<button onClick={handleAddUser} disabled={mutation.isPending}>
{mutation.isPending ? 'Adding...' : 'Add User'}
</button>
{mutation.isError && <p>Error adding user: {mutation.error.message}</p>}
{mutation.isSuccess && <p>User added successfully!</p>}
</div>
);
}
export default AddUserButton;