Introduction to TanStack Query: Supercharge Your Data Fetching in a React App
Tags: react, javascript, query, webdev
Published: 2023-10-18 13:51:15

###Introduction

The process of fetching data into a web application is an essential part of the development of web applications.

In this guide, you’ll learn how to fetch data into your React app and manage network request states with TanStack Query. React lets you fetch data flexibly. You can fetch data in the `useEffect` hook and manage the state with `useState`.

While this works fine for your basic data fetching needs, it works well for client state management. However, when you need to manage your application server state React hooks do not do the job well enough.

There are several ways to fetch data in a React app. This guide shows you what TanStack Query is, and how to get started with using it alongside a demo API (Application Programming Interface) to get a hands-on experience.

You will fetch data from the JSON Placeholder API users endpoint, handle the network requests states with TanStack Query, and also show the returned data on the User Interface (UI).

###Prerequisite

Before you go ahead with this technical write-up, it is important that you already have some understanding of JavaScript and React. Ideally, to get the most out of this lesson you should have an understanding of JS functions, React components, and hooks.

###What is Data Fetching?

When you look up the meaning of [data](https://www.oxfordlearnersdictionaries.com/definition/american_english/data) in the Oxford Dictionary, data is defined as “facts or information, especially when examined and used to find out things or to make decisions”.

From the definition above you can see that data is what you as a developer would work with. Based on the peculiarity of your project, the way you present the data is thus important to help the consumers make an informed decision or find out things.

Data fetching is the process of retrieving information from a data source. Examples of data sources are a database storage system, an Application Programming Interface (API), or a headless Content Management System (CMS).

####Concept of Data Fetching in a React App

You can fetch data into your React web app from a database, API, or headless CMS. To fetch data into your React web app, use the Fetch API tool built into most modern web browsers or third-party libraries like Axios and ky fetch.

Fetching data is a side effect in React, you'll need to do it inside the `useEffect` hook. There are some gotchas with this approach, especially when you are fetching asynchronous data. You have to manage the states yourself. This is not robust enough, so there are some third-party libraries you can use to fetch data instead of fetching the data inside the `useEffect` hook.

####Data Fetching Tools

There are several third-party libraries you can use to handle data fetching in your React web app. Here are two third-party libraries that are quite popular: 

- TanStack Query (React Query)
- State While Revalidate (SWR)

###What is TanStack Query?

TanStack Query is a powerful server state management library for React, Vue, Svelte, and JavaScript. This means that you can use TanStack Query for any of the JavaScript frameworks/libraries.

With `useEffect` and `useState` hooks, you can fetch your data and manage the network request state. However, handling stuff like caching, and revalidating stale data requires a lot more work with this approach.

TanStack Query helps you to write your fetching logic in a declarative way. In addition to data fetching and state management, it also accommodates caching, stale data revalidation, and optimistic updates with little to no configuration.

Originally known as React Query, TanStack Query is now available in other JavaScript frameworks/libraries with recent updates, and you will learn the React version of TanStack Query in this tutorial.

####Features of TanStack Query

Using TanStack Query has a lot of benefits because of the features it has out of the box. Below is a highlight of some of the features it offers:

- Prefetching data
- Caching
- Revalidating stale data
- Pagination
- Data mutations

####How TanStack Query helps with state management, synchronization, caching, and error handling

It is quite important to note that TanStack Query does not do the data fetching for you as some would think. 

Rather it’s more like a data fetching management tool, which means that you still have to fetch the data using either the browser-supported Fetch API, Axios, or Ky fetch. While TanStack Query takes it up from there and manages the server state with a `queryKey` and `queryFn`.

TanStack Query is available globally, so you don’t have to make network requests often. The `queryKey` is used to serve cached data which can still be used while revalidated data is fetched. This is similar to the Next JS Stale While Revalidate (SWR) data fetching library.

Remember you still have to fetch the data into your React app using either Fetch API or any of the third-party libraries. The data fetching function is often an asynchronous function that you have to pass to the `queryFn`. You will see all this in a demonstration shortly.

TanStack Query offers the different states of network requests like `isLoading`, `isError`, `success`, and the `data` itself out of the box to use without using the `useState` hook to handle it.

###Installing TanStack  Query in a React App

To set up TanStack Query, you need to create a React app.

Proceed to create a React app using Vite. Run this command in your command line tool:

**NPM**

`npm create vite@latest`

**Yarn**

`yarn create vite`

####Install TanStack Query

You can install TanStack Query in your React App with NPM or Yarn.

Ensure to install the react version as shown below.

**NPM**

`npm i @tanstack/react-query`

**Yarn**

`yarn add @tanstack/react-query`

###Using TanStack Query

**Import TanStack Query**

When using TanStack Query, you need to import it and make it available globally in your React app. To achieve this, import it at the top level of your React app which is inside the **main.jsx** file in the src folder.

To get started with this, the first line of action you need to carry out is to create a provider, which is `QueryClientProvider` component. The `QueryClientProvider` component wraps your entire app. The `QueryClientProvider` provides and connects `QueryClient` to your application.

You may be asking, what then is a `QueryClient`? 

`QueryClient` is a class from the TanStack query library that is used to fetch and cache a query. To use `QueryClient`, you pass it as a prop to `<QueryClientProvider>`.

Here is how your **main.jsx** file should look like:

```jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
// import QueryClientProvider and QueryClient from tanstack/react-query
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
import './index.css';

// Create a query client class
const queryClient = new QueryClient();

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
    </QueryClientProvider>
  </React.StrictMode>
```

###Fetching Data

For a quick walkthrough of how you can get started with using TanStack Query in your React app.  You’ll make a fetch request to JSON Placeholder to fetch users.

####useQuery Hook

The `useQuery` hook grants you access to your data in the **FetchUsers** component without the need for a `useState` and `useEffect` hooks to fetch your data.

Also, you get access to other network request query states such as `isLoading`, `error`, `isFetching`, `status`, and a whole bunch of other states. See the official docs to read more on [useQuery](https://tanstack.com/query/v4/docs/react/reference/useQuery).

Proceed to create a component folder inside the src folder, inside the component folder, create a **FetchUser.jsx** component.

Import the **FetchUsers.jsx** component inside the App.jsx file:

```jsx
import FetchUsers from './components/react-query/FetchUsers';

function App() {
  return (
    <div>
      <FetchUsers />
    </div>
  );
}

export default App;
```

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

// Fetch users from JSON Placeholder using the Fetch API
async function fetcher() {
  const response = await fetch('https://jsonplaceholder.typicode.com/users');

  if (!response.ok) {
    const message = `An error has occured: ${response.status}`;
    throw new Error(message);
  }

  const json = await response.json();

  return json;
}

function FetchUsers() {
  const {
    data: users,
  } = useQuery({
    queryKey: ['users'],
    queryFn: fetchUser,
  });

  return (
    <div>
      {users?.map((user) => (
        <li key={user.id}>{user.username}</li>
      ))}
    </div>
  );
}

```
Here is an explanation of what the code above does:

To fetch data using react-query, you have to first import the `useQuery` hook which is a custom hook in react-query. You proceed to fetch the data; in this example, you'll be using JSON Placeholder (https://jsonplaceholder.typicode.com/users) endpoint and the browser Fetch API.

Also, if you noticed that `data` is annotated with the word `user`. This is a common pattern instead of using the general word data to make it easier to read and debug. 

Note that your data can be anything.

Inside the **FetchUsers** react component, you call the `useQuery` hook and pass it an object. Inside the object, you have the `queryKey` and `queryFn`. 

####queryKey

When you make a network request for the first time. React Query caches the data internally with the `queryKey`. On subsequent network requests, React Query checks if the data is cached, if it is, React Query serves the cached data instead of making another network request.

The `queryKey` is also used for prefetching data when the dependencies change. A good example is when you add or delete from the list of users, the `queryKey` updates the query. 

Another use of `queryKey` is to ensure that users are getting an updated UI by invalidating cached data to show updated data.

It is important to note that the `queryKey` is usually an array, and you can pass more than one item to the array.

####queryFn

The second part, which is `queryFn` is your data fetching function which is often an asynchronous function. 

From the sample code, you can see that the `fetcher` function is passed to the `queryFn` by reference. You can also make your fetch request inside the `useQuery` hook. However, this approach makes the code easier to read.

###Loading and Error State

To indicate the status of the query when using Tanstack Query, the `isLoading` and `isError` states are used. 

The `isLoading` state is set to true when the query is in progress but there is not yet any data available. 

The `isError` state is set to true when an error occurs during the query. While the query is being executed, these states can display a loading spinner or an error message to the user

Back to the code, to add the `isLoading`, `isError`, and `error` state status, you'll add them to the `useQuery` hook.

Here is the code sample:

```jsx
// Add isLoading, isError, and error state to useQuery hook inside the FetchUser component
...
const {
    isLoading,
    isError,
    error,
    data: users,
  } = useQuery({
    queryKey: ['users'],
    queryFn: fetchUser,
  });

// Loading state
if (isLoading) return <p>Loading...</p>;

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

To see the loading and error state in action, carry out the following steps:

#####Loading State

Open your browser console by pressing:

- Control + Shift + I on Windows
- Command + Option + I on Mac
- Go to the Network tab, and change it from No Throttling to Slow 3G.
- Realod the page, you'll see the Loading... paragraph text.

#####Error State

To simulate an error, you can provide an invalid URL (https://xjsonplaceholder.typicode.com/users).

```jsx
// Invalidating the URL
async function fetchUser() {
  const response = await fetch('https://xjsonplaceholder.typicode.com/users');
}
```

You should see this error message: `Error: Failed to fetch`

In comparison to using the `useEffect` and `useState` hooks to fetch and manage data in React, this approach is straightforward and easier to maintain.


###Conclusion

In this guide, you learned how to use TanStack Query (React Query) to fetch data and manage state and why it is a better alternative to the `useEffect` and `useState` hooks in React. 

You learned how to set up React Query in your React and make it globally available by wrapping your React app with the `QueryClientProvider`. You created a `QueryClient` class and passed it as a prop to `QueryClientProvider`.

A **FetchUsers** component was created and, you learned how to use the `useQuery` hook. The functions of the `queryKey` and `queryFn` as well as managing network request query states in React Query.