What is React Query?

Scaibu
5 min readNov 18, 2024

--

React Query is a powerful data-fetching and state management library designed specifically for managing server state in React applications. Unlike traditional state management tools such as Redux or Context API, React Query simplifies the handling of server state by providing robust tools for data fetching, caching, synchronization, and updates.

Tanner Linsley created React Query, which is part of the TanStack Query ecosystem and extends its capabilities to other popular frontend frameworks, including Vue, SolidJS, and Svelte. Written in TypeScript, React Query provides additional type safety through features like type inference and type narrowing, which makes it ideal for scalable and maintainable projects. It also supports React Native, enabling mobile app developers to leverage its capabilities seamlessly.

Why React Query?

Challenges with Server State

Managing server state is more complex than handling local UI state. Server state involves data fetched from APIs, databases, or other remote sources, and it often requires careful handling to ensure consistency, reliability, and performance. Below are some challenges React Query addresses:

  1. Data-Fetching Logic: Writing code to handle API requests, loading states, error handling, and retries often results in repetitive, boilerplate-heavy implementations.
  2. Caching: Efficiently caching data for reuse across the application is complex and error-prone.
  3. Stale Data: Determining when data is no longer valid and needs to be refetched can become tedious to manage.
  4. Synchronization: Keeping local state in sync with server updates, especially in real-time applications, requires significant effort.
  5. Optimistic Updates: Providing a responsive UI experience by predicting and temporarily applying updates before server confirmation can be challenging.
  6. Paginated and Infinite Loading: Managing paginated API responses and implementing infinite scrolling requires considerable custom logic.
  7. Network Status Awareness: Handling scenarios where users lose connectivity and need offline support or retries.

How React Query Solves These Challenges

React Query simplifies server state management with the following features:

  • Automatic Caching: Stores query results in a centralized cache, enabling efficient data reuse.
  • Stale-While-Revalidate Pattern: Automatically refetches data in the background when it becomes stale, ensuring data freshness without blocking the UI.
  • Simplified API: Provides hooks like useQuery and useMutation for effortless data-fetching and mutation operations.
  • Real-Time Updates: Supports features like subscriptions and polling for real-time applications.
  • Robust Error Handling: Automatically retries failed queries based on a customizable retry mechanism.
  • Offline Support: Tracks network status and retries queries when connectivity is restored.

Core Concepts of React Query

React Query’s foundation lies in three core concepts: queries, mutations, and the QueryClient.

1. Queries: Fetching Data

A query is used to fetch data from a remote source, such as a REST API or GraphQL endpoint. In React Query, the useQuery hook is used to manage the lifecycle of a query, including:

  • Fetching data.
  • Storing it in the cache.
  • Handling loading and error states.
  • Automatically refetching stale data.

How useQuery Works

The useQuery hook accepts:

  1. Query Key: A unique identifier for the query, typically an array (e.g., ['todos']).
  2. Query Function: A function that returns a promise resolving to the fetched data.
  3. Options (optional): Configuration options, such as caching behavior, refetch intervals, etc.

Example: Fetching Users

import { useQuery } from '@tanstack/react-query';

const fetchUsers = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) throw new Error('Error fetching users');
return response.json();
};

function UserList() {
const { data, isLoading, isError, error } = useQuery(['users'], fetchUsers);

if (isLoading) return <p>Loading...</p>;
if (isError) return <p>Error: {error.message}</p>;

return (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}

2. Mutations: Modifying Data

A mutation modifies server-side data by creating, updating, or deleting resources. Unlike queries, mutations are non-idempotent and require careful handling, especially for optimistic updates.

React Query’s useMutation hook simplifies mutation operations by handling:

  • Success and error states.
  • Cache invalidation for affected queries.
  • Optimistic updates with rollback in case of failure.

Example: Adding a New User

import { useMutation, useQueryClient } from '@tanstack/react-query';

const addUser = async (user) => {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user),
});
if (!response.ok) throw new Error('Error adding user');
return response.json();
};

function AddUser() {
const queryClient = useQueryClient();
const mutation = useMutation(addUser, {
onSuccess: () => {
queryClient.invalidateQueries(['users']); // Refresh cached users
},
});

const handleAddUser = () => {
mutation.mutate({ name: 'New User', email: 'newuser@example.com' });
};

return (
<button onClick={handleAddUser} disabled={mutation.isLoading}>
{mutation.isLoading ? 'Adding...' : 'Add User'}
</button>
);
}

3. QueryClient: Managing Queries

The QueryClient is the backbone of React Query. It provides a centralized API for managing:

  • Global cache behaviour.
  • Query and mutation lifecycle events.
  • Prefetching and invalidation of queries.

Example: Setting up QueryClient

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

function App() {
return (
<QueryClientProvider client={queryClient}>
{/* Application Components */}
</QueryClientProvider>
);
}

Key Features of React Query

React Query offers an extensive set of features that streamline server state management:

1. Caching and Stale Management

React Query uses a stale-while-revalidate strategy to ensure data is fresh while avoiding unnecessary network requests. Cached data remains available until it is marked stale based on configurable time-to-stale settings.

2. Automatic Background Refetching

When data becomes stale, React Query automatically prefetches it in the background, ensuring that the UI always displays fresh content.

3. Optimistic Updates

Mutations can be configured for optimistic updates, which temporarily update the UI before server confirmation. If the mutation fails, the UI reverts to the previous state.

4. Pagination and Infinite Queries

React Query provides utilities for handling paginated APIs and implementing infinite scrolling using the useInfiniteQuery hook.

Example: Infinite Scrolling

import { useInfiniteQuery } from '@tanstack/react-query';

const fetchItems = async ({ pageParam = 1 }) => {
const response = await fetch(`/api/items?page=${pageParam}`);
return response.json();
};

function InfiniteScroll() {
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery(
['items'],
fetchItems,
{
getNextPageParam: (lastPage) => lastPage.nextPage,
}
);

return (
<div>
{data.pages.map((page) =>
page.items.map((item) => <p key={item.id}>{item.name}</p>)
)}
{hasNextPage && (
<button onClick={() => fetchNextPage()}>Load More</button>
)}
</div>
);
}

Advanced Features

1. Dependent Queries

Queries can be chained, where one query executes only after another has successfully resolved.

2. Prefetching

React Query allows preloading of data that may be needed in the near future.

3. Network Awareness

React Query tracks network connectivity and automatically retries failed queries when the connection is restored.

Installation and Setup

To get started, install React Query and the Devtools:

npm install @tanstack/react-query @tanstack/react-query-devtools

For TypeScript support, no additional steps are required as React Query is written in TypeScript.

Conclusion

React Query revolutionizes server state management by simplifying data-fetching, caching, synchronization, and updates. Its powerful API, combined with features like background refetching, optimistic updates, and offline support, makes it an essential tool for modern React development. Whether you’re building a small application or a large-scale enterprise solution, React Query helps you deliver faster, more responsive, and maintainable applications.

--

--

Scaibu
Scaibu

Written by Scaibu

Revolutionize Education with Scaibu: Improving Tech Education and Building Networks with Investors for a Better Future

No responses yet