What is react-query? Why should we use react-query?
Tags: typescript, react, webdev, beginners
Published: 2024-04-27 01:00:00

## Introduction 📯📯📯
You might have heard or seen others mention the **react-query** library quite often. Why should we use **react-query** when we can use **useEffect** to fetch data from an API? This article will answer that question.

## What is react-query? 🌱🌱🌱
react-query is a set of hooks for fetching, caching, and updating asynchronous data in React.

Simply put, react-query is a library for fetching, caching, and updating asynchronous data when used in React.

## Why should we use react-query? 🌱🌱🌱
Normally, there are many ways to fetch data from a server. Some popular methods include using **useEffect** and **useState**, or using a state management library like **redux**.

```tsx
export const Page = () => {
  const [data, setData] = useState();
    useEffect(() => {
      const loadData = async () => {
        const response = await fetch(hostAPI).then(response => response.json());
        setData(response)
    }
    loadData()
  })
  return <DisplayData />
}
```
This method works fine, but it’s quite cumbersome. You have to write a bunch of code just to fetch data from the server and display it to the user. This method has the advantage of being simple to use, easy to read, and easy to understand. However, in cases where complex processing is required, such as caching response data, you need to implement a lot more. Luckily, react-query will support us in these cases.

## Using react-query 🌱🌱🌱
**react-query** provides simple hooks to fetch and update data from the server. It supports **caching**, **re-fetching**, and much more.

First, let’s learn how to fetch data using useQuery.

### useQuery ⭐⭐
To use the useQuery hook, you must pass at least two parameters:

The first parameter is the query key, which is a string[] data type, used for re-fetching, caching, and sharing data between components.
The second parameter is a function typically used to call an API, which returns a promise used to resolve data or throw an error.
The third parameter is the options (optional) that useQuery supports.
useQuery returns necessary information such as data, isFetching, or isError. We then use this information to display appropriate information.

Here’s an example:
```tsx
import {useQuery} from '@tanstack/react-query'

const Page = () => {
  const { data, isFetching, isError } = await useQuery(['todo'], () => fetch(hostAPI).then(response => response.json()))
  if (isFetching) {
    return <Loading />
  }
  if (isError) {
    return <Error />
  }
  return <DisplayData />
}
```

### useMutation ⭐⭐
useMutation is used to create/update/delete data. This hook includes the following parameters:

The first parameter is the mutation key (similar to the query key).
The second parameter is a function that returns a promise to resolve data or throw an error.
The third parameter is the options.
The result returned by the useMutation hook is isFetching, isError, data similar to useQuery, in which there is an additional mutate function used to pass params when calling the API to create/update data.

Here's how to use it:
```tsx
import {useMutation} from '@tanstack/react-query'

export const addProduct = (product: Partial<Product>): Promise<Product> =>
  fetch(`${hostAPI}/add`, {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(product),
  })
  .then(res => res.json())
  .catch(() => {
    throw new Error('Failed addProduct')
  })

function Page() {
  const {mutate, isError, isFetching, data} = useMutation(['add-product'], addProduct)
  return (
    <div>
      <button onClick={() => mutate({id: 1, title: 'title 1'})}>
        Add product
      </button>
    </div>
  )
}
```

## Example of use with option param 🍬🍬🍬

### Pre-fetching data ⭐⭐
In case you have a list of articles belonging to a series on a certain topic, you would want the system to automatically fetch data of the next article when the user clicks on any article. We can use react-query to implement this feature as follows:
```tsx
import {useQuery, useQueryClient} from '@tanstack/react-query'

export default function Index() {
  const [id, setId] = useState<number>(1)
  const queryClient = useQueryClient()
  const {data, error, isFetching} = useQuery(['list-post', id], () => getPostDetail(id), {
    onSuccess: () => {
      const nextID = id + 1
      // prefetch data, next time must request this queryKey it will use the cache data
      queryClient.prefetchQuery(['list-post', nextID], () => getPostDetail(nextID))
    },
    onError: console.error, // log error
  })
  return <DisplayData />
}
```
Here, the option object takes in two functions: **onSuccess** and **onError**:

- **onSuccess** runs when the query is executed successfully. I use the method **queryClient.prefetchQuery** (useQueryClient) to prefetch the data of the next post. If the user accesses any post, the data of the next post will be fetched in advance so that it can be used immediately when the user accesses that post.
- **onError** runs if the query encounters an error.

### Optimistic UI updates ⭐⭐
This is the case when we want to update the UI before receiving the response data result (and will update the accurate data later).

For example, when clicking like, the UI will render as liked during the API call process. After getting the response data, the UI will be updated according to the corresponding status. This way, the user won't have to wait too long for this function (helping to enhance the user experience).
```tsx
export default function Page() {
  const [isLike, setLike] = useState<boolean>(false)
  const {mutate} = useMutation(['change-status'], updateLike, {
    onMutate: () => setLike(true), // set status while waiting reponse
    onSuccess: setLike, // set status after receiving response data
    onError: console.error,
  })
  return isLike
}2
```

- **useMutate** runs before a mutation is successful or encounters an error. At this point, we’ll make preliminary changes to the state here.
- **onSuccess** runs after the mutation has been executed (regardless of success or error). At this point, we’ll update the state depending on the response data.

## Conclusion 🏆🏆
React-query is a library that readily supports many features related to data requests, caching, and more. It also has many other great features that you can check out in more detail [here](https://tanstack.com/query/latest/docs/framework/react/overview).

**_Don't hesitate to leave your thoughts in the comments section, and remember to like, share, and follow for more insightful content in the future!_**

**_If you found this content helpful, please visit [the original article on my blog](https://howtodevez.blogspot.com/2024/03/what-is-react-query-why-should-we-use.html) to support the author and explore more interesting content._**🙏🙏

<a href="https://howtodevez.blogspot.com/2024/03/sitemap.html" target="_blank" rel="noreferrer"><img src="https://img.shields.io/badge/Blogger-FF5722?style=for-the-badge&logo=blogger&logoColor=white" width="36" height="36" alt="Blogspot" /></a><a href="https://dev.to/chauhoangminhnguyen" target="_blank" rel="noreferrer"><img src="https://img.shields.io/badge/dev.to-0A0A0A?style=for-the-badge&logo=dev.to&logoColor=white" width="36" height="36" alt="Dev.to" /></a><a href="https://www.facebook.com/profile.php?id=61557154776384" target="_blank" rel="noreferrer"><img src="https://img.shields.io/badge/Facebook-1877F2?style=for-the-badge&logo=facebook&logoColor=white" width="36" height="36" alt="Facebook" /></a><a href="https://x.com/DavidNguyenSE" target="_blank" rel="noreferrer"><img src="https://img.shields.io/badge/X-000000?style=for-the-badge&logo=x&logoColor=white" width="36" height="36" alt="X" /></a>