Understanding React Query
Simplifying Data Fetching in React Applications
React 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. This article will introduce you to React Query, its key features, and how to get started using it in your React projects.
What is React Query?
React 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.
Key Features
- Declarative Data Fetching: React Query promotes a declarative approach to data fetching. You define queries and mutations using hooks like
useQuery
anduseMutation
. This leads to cleaner and more organized code. - Automatic Caching: React Query includes a built-in cache that stores query results. It automatically updates data when mutations occur, ensuring your UI remains consistent.
- Background Data Sync: It can automatically refetch data in the background, keeping your data fresh without manual intervention.
- Pagination and Infinite Scrolling: React Query provides utilities for handling pagination and infinite scrolling effortlessly.
- Optimistic Updates: You can implement optimistic updates with ease, making your app feel more responsive.
Getting Started with React Query
Let’s dive into a basic example to see how simple it is to get started with React Query. The first thing you need to do is install the @tanstack/react-query
library. I will use npm for the execution.
npm install @tanstack/react-query
After the library is installed in our application, create a provider and client to use React Query. You can create it in the index.tsx
file in the src
folder.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
const queryClient = new QueryClient();
root.render
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
After that, you can immediately use React Query Hooks. Let’s apply it to the App.tsx
script.
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { useQuery } from '@tanstack/react-query';
function App() {
const userData = useQuery(
['users'],
() => {
return fetch('https://jsonplaceholder.typicode.com/users').then(response => response.json());
},
{
enabled: false,
}
);
return (
<div>
<div>
<button onClick={() => userData.refetch()}>Get Users</button>
<div>
{userData.isFetching && (
<div>Fetching user data...</div>
)}
{userData.isError && (
<div>{`Error get data!!!`}</div>
)}
{userData.data && userData.data.length > 0 && userData.data.map((user: any) => (
<div>{user.name}</div>
))}
</div>
</div>
</div>
);
}
export default App;
In this example, we use useQuery
to fetch a list of users. React Query handles the fetching state, error handling, and caching behind the scenes.
When we click the Get Users
button, we are fetching data from the API. Because the amount of data is small, the fetching process becomes less visible because it is too fast.
Apart from useQuery, we also have useMutation where these hooks are almost the same as useQuery, but are used to mutate data. Below I show an example of its use. Just add this code.
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { useQuery, useMutation } from '@tanstack/react-query';
function App() {
const userData = useQuery(
['users'],
() => {
return fetch('https://jsonplaceholder.typicode.com/users').then(response => response.json());
},
{
enabled: false,
}
);
const mutatePost = useMutation(
['posts'],
(newPost: any) => {
return fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify(newPost),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
}).then((response) => response.json())
}
)
return (
<div>
<div>
<button onClick={() => userData.refetch()}>Get Users</button>
<div>
{userData.isFetching && (
<div>Fetching user data...</div>
)}
{userData.isError && (
<div>{`Error get data!!!`}</div>
)}
{userData.data && userData.data.length > 0 && userData.data.map((user: any) => (
<div>{user.name}</div>
))}
</div>
</div>
<hr />
<div>
<button onClick={() => mutatePost.mutate({ title: 'First Post', body: 'First Post Body', userId: 1 })}>Add New Post</button>
<div>
{mutatePost.isLoading && (
<div>Adding new post...</div>
)}
{mutatePost.isError && (
<div>{`Error add new post!!!`}</div>
)}
{mutatePost.data && (
<div>{`Success add new post with title : '${mutatePost.data.title}'`}</div>
)}
</div>
</div>
</div>
);
}
export default App;
In the example above we use useMutation to add a new post.
Difference between useQuery and useMutation
- Purpose:
useQuery
is for reading data, whileuseMutation
is for modifying data. - Typical Use Case:
useQuery
is used when you want to fetch and display data, whileuseMutation
is used when you want to make changes to that data. - Return Values:
useQuery
returns{ data, error, isLoading, isFetching }
, whileuseMutation
returns{ mutate, data, error, isError, isLoading, isSuccess }
. - Error Handling: Both hooks handle errors, but
useMutation
provides additional features for handling optimistic updates and rollbacks in case of errors during mutations.
Conclusion
React 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, React Query’s simplicity and powerful features will help you manage your data effectively.
By simplifying data management, React 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.