Integrating Axios with React Query
Integrating Axios with React Query (TanStack Query) provides a robust solution for server-state management and asynchronous data fetching in React applications. This guide demonstrates how to configure Axios instances, write clean query functions, handle parameters dynamically, execute mutations for data updates, and manage errors effectively within the TanStack Query lifecycle.
Setting Up an Axios Instance
Creating a pre-configured Axios instance ensures consistent base URLs, headers, and interceptors across your application.
// apiClient.js
import axios from 'axios';
const apiClient = axios.create({
baseURL: 'https://api.example.com/v1',
headers: {
'Content-Type': 'application/json',
},
});
export default apiClient;Basic Data Fetching with
useQuery
React Query's queryFn requires a function that returns a
Promise. When using Axios, return response.data so the
query receives the direct payload rather than the entire Axios response
object.
// useGetUsers.js
import { useQuery } from '@tanstack/react-query';
import apiClient from './apiClient';
const fetchUsers = async () => {
const response = await apiClient.get('/users');
return response.data;
};
export const useGetUsers = () => {
return useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
});
};Handling Dynamic Parameters
To pass dynamic parameters (such as resource IDs or filters) to an Axios request, pass them through the query function or read them directly from the query key context.
// useGetUserById.js
import { useQuery } from '@tanstack/react-query';
import apiClient from './apiClient';
const fetchUserById = async ({ queryKey }) => {
const [_key, userId] = queryKey;
const response = await apiClient.get(`/users/${userId}`);
return response.data;
};
export const useGetUserById = (userId) => {
return useQuery({
queryKey: ['user', userId],
queryFn: fetchUserById,
enabled: Boolean(userId), // Prevents execution if userId is undefined
});
};Executing Mutations with
useMutation
For POST, PUT, PATCH, and
DELETE requests, wrap Axios calls inside the
mutationFn of the useMutation hook.
// useCreateUser.js
import { useMutation, useQueryClient } from '@tanstack/react-query';
import apiClient from './apiClient';
const createUser = async (newUserData) => {
const response = await apiClient.post('/users', newUserData);
return response.data;
};
export const useCreateUser = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: createUser,
onSuccess: () => {
// Invalidate and refetch users query on successful creation
queryClient.invalidateQueries({ queryKey: ['users'] });
},
});
};Error Handling
Axios automatically throws an error for HTTP status codes outside the
2xx range, which React Query catches seamlessly. You can
access the structured Axios error inside your components:
const { data, error, isError, isLoading } = useGetUsers();
if (isLoading) return <div>Loading...</div>;
if (isError) return <div>Error: {error.response?.data?.message || error.message}</div>;