Get ready for your next interview with our comprehensive question library
React Query provides several core hooks:
useQuery: For fetching and caching datauseMutation: For creating, updating, or deleting datauseQueryClient: For accessing the query client instanceuseInfiniteQuery: For paginated or infinite scrolling datauseQueries: For running multiple queries in paralleluseIsFetching: For getting the number of currently fetching queriesuseIsMutating: For getting the number of currently running mutationsuseQuery for read operations and useMutation for write operations.Setting up React Query involves three main steps:
npm install @tanstack/react-query
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* Your app components */}
</QueryClientProvider>
);
}
import { useQuery } from '@tanstack/react-query';
function Posts() {
const { data, isLoading, error } = useQuery({
queryKey: ['posts'],
queryFn: () => fetch('/api/posts').then(res => res.json())
});
if (isLoading) return 'Loading...';
if (error) return 'Error occurred';
return <div>{/* Render posts */}</div>;
}
The useQuery hook accepts a configuration object with key properties:
const { data, isLoading, error, isError, isSuccess } = useQuery({
queryKey: ['posts', userId], // Unique identifier for the query
queryFn: () => fetchPosts(userId), // Function that returns a promise
enabled: !!userId, // Optional: conditionally enable the query
staleTime: 5 * 60 * 1000, // Optional: how long data stays fresh
refetchOnWindowFocus: false // Optional: disable refetch on window focus
});
Key properties:
queryKey: Unique identifier used for caching and invalidationqueryFn: Async function that fetches the dataenabled: Boolean to conditionally run the querystaleTime: Time in milliseconds before data is considered staledata: The fetched dataisLoading: True during the first fetcherror: Error object if the query failedisError/isSuccess: Boolean states for handling different scenariosThese two states serve different purposes:isLoading:
isFetching:const { data, isLoading, isFetching } = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts
});
// First load: isLoading = true, isFetching = true
// Background refetch: isLoading = false, isFetching = true
// With cached data: isLoading = false, isFetching = false
This distinction allows you to show different UI states - a full loading screen for initial loads and a subtle indicator for background updates.
Query keys are unique identifiers that React Query uses for caching, invalidation, and refetching. They must be arrays and are compared deeply.
Basic structure:
// Simple key
queryKey: ['posts']
// Key with parameters
queryKey: ['posts', userId]
// Key with complex parameters
queryKey: ['posts', { userId, status: 'published' }]
Key principles:
// These are different queries with separate cache
queryKey: ['posts'] // All posts
queryKey: ['posts', 1] // Posts for user 1
queryKey: ['posts', 2] // Posts for user 2
// Invalidation example
queryClient.invalidateQueries({ queryKey: ['posts'] }); // Invalidates all post queries
queryClient.invalidateQueries({ queryKey: ['posts', 1] }); // Only user 1's posts
Query keys enable React Query's intelligent caching and make it easy to manage related data.
useMutation is used for operations that create, update, or delete data (side effects). Unlike useQuery, mutations don't run automatically and must be triggered manually.
Basic usage:
const mutation = useMutation({
mutationFn: (newPost) => fetch('/api/posts', {
method: 'POST',
body: JSON.stringify(newPost)
}),
onSuccess: (data) => {
// Invalidate and refetch related queries
queryClient.invalidateQueries({ queryKey: ['posts'] });
},
onError: (error) => {
console.error('Failed to create post:', error);
}
});
// Trigger the mutation
const handleSubmit = (formData) => {
mutation.mutate(formData);
};
Key properties:
mutationFn: Function that performs the mutationonSuccess: Callback for successful mutationsonError: Callback for failed mutationsonSettled: Callback that runs regardless of success/failureReact Query provides built-in states for handling different scenarios:
Basic approach:
const { data, isLoading, error, isError } = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts
});
if (isLoading) return <div>Loading posts...</div>;
if (isError) return <div>Error: {error.message}</div>;
return (
<div>
{data.map(post => (
<div key={post.id}>{post.title}</div>
))}
</div>
);
const { data, isLoading, error, isError } = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
retry: 3, // Retry failed requests 3 times
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000)
});
// Custom error boundary
if (isError) {
return (
<div>
<h3>Something went wrong</h3>
<p>{error.message}</p>
<button onClick={() => refetch()}>Try Again</button>
</div>
);
}
For mutations:
const mutation = useMutation({
mutationFn: createPost,
onError: (error, variables, context) => {
// Handle mutation errors
setErrorMessage(error.message);
}
});
return (
<div>
<button
onClick={() => mutation.mutate(postData)}
disabled={mutation.isPending}
>
{mutation.isPending ? 'Creating...' : 'Create Post'}
</button>
{mutation.isError && <div>Error: {mutation.error.message}</div>}
</div>
);
Upgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumAccess all premium content - interview questions, and other learning resources
We regularly update our features and content, to ensure you get the most relevant and updated premium content.
1000 monthly credits
Cancel anytime