Mastering React Query: A Comprehensive Guide for Your React Projects

  • 2024/10/29
  • Mastering React Query: A Comprehensive Guide for Your React Projects はコメントを受け付けていません

Introduction

As front-end developers, we often need to manage and synchronize remote data in our React applications. Fetching data from APIs, caching it, keeping it in sync with the UI, and handling loading and error states can be challenging. Traditionally, we relied on libraries like Redux or native useState and useEffect hooks to manage data fetching. However, these solutions can become verbose and error-prone.

This is where React Query comes to the rescue. React Query simplifies data-fetching logic and provides powerful tools to handle server-state seamlessly. This guide will introduce you to React Query, discuss its advantages, and walk through how to use it in a React project.

What is React Query?

React Query is a powerful library for managing server-state in React applications. It provides an intuitive API to fetch, cache, and update data efficiently. With React Query, you no longer need to manage state manually with useState or useReducer for every data-fetching task.

Key benefits of using React Query:

  1. Simplifies data fetching and state management.
  2. Built-in caching and background synchronization.
  3. Automatic refetching on network recovery or focus.
  4. Out-of-the-box loading and error handling.
  5. Support for pagination, infinite queries, and optimistic updates.

Setting up React Query in Your React Project

Before diving into how to use React Query, let’s start by adding it to a React project.

Installation

First, install the necessary dependencies. If you don’t have a React project, you can create one using Create React App:

npx create-react-app react-query-demo

cd react-query-demo
Now, install React Query:
npm install @tanstack/react-query

You’ll also need to install the React Query DevTools for debugging purposes:

npm install @tanstack/react-query-devtools

Core Concepts of React Query

Before diving into practical examples, it’s essential to understand some core concepts:

  • Query: Used to fetch data from a server.
  • Mutation: Used to create, update, or delete data on the server.
  • Query Client: A shared instance that manages queries and their states.
  • Query Keys: Unique identifiers for each query to cache and manage them efficiently.

Step-by-Step Guide to Using React Query

1. Setting Up the QueryClient and QueryClientProvider

To use React Query, you need to wrap your application with a QueryClientProvider. It provides the QueryClient instance throughout your component tree.

In src/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import App from './App';

// Create a QueryClient instance
const queryClient = new QueryClient();

ReactDOM.render(
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>,
document.getElementById('root')
);

The QueryClientProvider wraps the application, making the QueryClient available for all components. The React Query DevTools allow you to debug and monitor queries in development mode.

2. Basic Data Fetching with React Query

To fetch data from an API, you use the useQuery hook. Let’s build a simple example to fetch posts from a public API.

In src/App.js:

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

const fetchPosts = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
};

function App() {
const { data, error, isLoading, isError } = useQuery(['posts'], fetchPosts);

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

return (
<div>
<h1>Posts</h1>
<ul>
{data.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}

export default App;

Explanation

  • useQuery: The useQuery hook takes two parameters: a unique query key (['posts']) and a function to fetch the data.
  • Loading and Error Handling: React Query provides isLoading and isError states to handle the fetching state and errors.

3. Query Caching and Background Sync

React Query caches the data automatically. You can configure how often it refetches the data and when to invalidate the cache.

Refetching on Window Focus

By default, React Query refetches data when the window regains focus. This ensures the UI always displays the latest data.

Stale Time and Cache Time

  • Stale Time: The time during which the data is considered fresh. After this period, React Query will mark the data as stale and may refetch it.
  • Cache Time: The time the data stays in cache after becoming stale.
const { data, isLoading } = useQuery(['posts'], fetchPosts, {
staleTime: 10000, // 10 seconds
cacheTime: 300000, // 5 minutes
});

4. Using Mutations to Create, Update, and Delete Data

Mutations in React Query are used for creating, updating, or deleting data on the server. Let’s look at an example of adding a new post.

In src/AddPost.js:

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

const addPost = async (newPost) => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newPost),
});
return response.json();
};

function AddPost() {
const queryClient = useQueryClient();
const [title, setTitle] = useState('');

const mutation = useMutation(addPost, {
onSuccess: () => {
// Invalidate and refetch posts
queryClient.invalidateQueries(['posts']);
},
});

const handleSubmit = (e) => {
e.preventDefault();
mutation.mutate({ title });
};

return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Enter post title"
/>
<button type="submit">Add Post</button>
</form>
);
}

export default AddPost;

Explanation

  • useMutation: The useMutation hook is used to perform POST, PUT, or DELETE operations.
  • Query Invalidation: After successfully adding a post, we invalidate the ['posts'] query to refetch and display the updated list.

5. Handling Paginated and Infinite Queries

React Query supports pagination and infinite scrolling with minimal setup.

const fetchPaginatedPosts = async ({ pageParam = 1 }) => {
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts?_page=${pageParam}&_limit=10`
);
return res.json();
};

const { data, fetchNextPage, hasNextPage } = useInfiniteQuery(
['paginatedPosts'],
fetchPaginatedPosts,
{
getNextPageParam: (lastPage, pages) => {
return lastPage.length ? pages.length + 1 : undefined;
},
}
);

Conclusion

React Query is a game-changer for managing server-state in React applications. It simplifies data-fetching logic, eliminates the need for complex state management, and ensures your UI stays in sync with the backend. Whether you need caching, background syncing, or paginated queries, React Query provides robust tools to handle these scenarios.

Key Takeaways

  1. React Query reduces the complexity of state management for server-state.
  2. Built-in caching, refetching, and background sync improve the user experience.
  3. Mutations make it easy to handle CRUD operations efficiently.
  4. React Query DevTools offer great insight into query behavior and debugging.

By using React Query, you can focus more on building features and less on managing state, resulting in cleaner, maintainable code.

Give React Query a try in your next project and see how it simplifies your data-fetching workflow!

References Links

TanStack Homepage

React-query Docs

関連記事

カテゴリー:

ブログ

情シス求人

  1. チームメンバーで作字やってみた#1

ページ上部へ戻る