Tanstack Query, AKA React Query, is a popular library for fetching data in React applications. React Query simplifies the process of fetching, caching, and updating data in web applications. This article will discuss using React Query to handle data fetching in a React application.

Installing and Setting Up React Query

You can install React Query using npm or yarn. To install it using npm, run the following command in your terminal:

        npm i @tanstack/react-query

To install it using yarn, run the following command in your terminal:

        yarn add @tanstack/react-query

After installing the React Query library, you wrap the entire application in the QueryClientProvider component. The QueryClientProvider component wraps your entire application and provides an instance of the QueryClient to all its child components.

The QueryClient is the central piece of React Query. The QueryClient manages all data fetching and caching logic. The QueryClientProvider component takes the QueryClient as a prop and makes it available to the rest of your application.

To make use of the QueryClientProvider and the QueryClient in your application, you must import them from the @tanstack/react-query library:

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

const queryClient = new QueryClient();

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

Understanding the useQuery Hook

The useQuery hook is a function provided by the React Query library, which fetches data from a server or API. It accepts an object with the following properties: queryKey (the key of the query) and queryFn (a function that returns a promise that resolves to the data you want to fetch).

The queryKey identifies the query; it must be unique for each query in your application. The key can be any value, such as a string, an object, or an array.

To fetch data using the useQuery hook, you need to import it from the @tanstack/react-query library, pass a queryKey and use the queryFn to fetch the data from an API.

For example:

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

function Home() {

  const postQuery = useQuery({
    queryKey: ['posts'],
    queryFn: async () => {
      const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
      const data = await response.data;
      return data;
    }
  })

  if( postQuery.isLoading ) return ( <h1>Loading....</h1>)
  if( postQuery.isError ) return (<h1>Error loading data!!!</h1>)
  
  return (
    <div>
      <h1>Home</h1>
      { postQuery.data.map( (item) => ( <p key={item.id}>{item.title}</p>)) }
    </div>
  )
}

export default Home;

The useQuery hook returns an object that contains information on the query. The postQuery object contains the isLoading, isError, and isSuccess states. The isLoading, isError, and isSuccess states manage the lifecycle of the data retrieval process. The postQuery.data property contains the data fetched from the API.

The isLoading state is a boolean value that indicates whether the query is currently loading data. When the isLoading state is true, the query is in progress, and the requested data is unavailable.

The isError state is also a boolean value indicating whether an error occurred during data retrieval. When isError is true, the query has failed to retrieve data.

The isSuccess state is a boolean value that indicates whether the query has successfully retrieved data. When isSuccess is true, you can display the data retrieved in your application.

Note you can access the queryKey using the queryFn. The queryFn takes a single argument. This argument is an object containing the parameters required for the API request. One of these parameters is the queryKey.

For example:

        useQuery({
    queryKey: ['posts'],
    queryFn: async (obj) => {
      console.log( obj.queryKey );
    }
  })

Dealing With Stale Data

React query provides many ways to deal with stale data. The React Query library ensures to automatically make a new fetch request to your API when the fetched data becomes stale. This guarantees that you are continually rendering the most up-to-date data.

You can control how fast your data becomes stale and the time interval between each automatic fetch request by utilizing the staleTime and refetchInterval options. The staleTime option is a property that specifies the number of milliseconds the cached data is valid before becoming stale.

The refetchInterval option is a property that specifies the number of milliseconds between each automatic fetch request of the React Query library.

For example:

        useQuery({
  queryKey: ['...'],
  queryFn: () => {...},
  staleTime: 1000;
})

In this example, the staleTime is 1000 milliseconds (1 second). The data fetched will become stale after 1 second, and then the React Query library will make another fetch request to the API.

Here you use the refetchInterval option to control the time interval between each automatic fetch request:

        useQuery({
  queryKey: ['...'],
  queryFn: () => {...},
  refetchInterval: 6000;
})

The refetchInterval is 6000 milliseconds (6 seconds). The React Query will automatically trigger a new fetch request to update the cached data after 6 seconds.

Understanding the useMutation Hook

The useMutation hook is a powerful tool in the React Query library. It performs asynchronous operation mutations, such as creating or updating data on a server. Using the useMutation hook, you can easily update your application state and user interface based on the response of the mutation.

Below, we have created an AddPost component that renders a form with an input field and a submit button. This form component will use the useMutation hook to update the state:

        import React from 'react'

function AddPost() {

    const[post, setPost] = React.useState({
        title: ""
    })

    function handleChange(event) {
        setPost( (prevState) => ({
            ...prevState,
            [event.target.name]: event.target.value
        }) )
    }

  return (
    <form onSubmit={handleSubmit}>
      <input
type="text"
placeholder='Add Title'
name='title'
onChange={handleChange}
value={post.title}
/>
      <button>Add Post</button>
    </form>
  )
}

export default AddPost;

Inside the AddPost component is a state post which serves as an object with one property, title.

The handleChange function updates the state post whenever users type in the input fields. After creating the AddPost component, we import the useMutation hook and use it to update the API.

For example:

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

const newPostMutation = useMutation({
    mutationFn: async () => {
      const response = await axios.post('<https://jsonplaceholder.typicode.com/posts>', {
        title: post.title,
      });
      const data = response.data;
      return data;
    }
 })

The useMutation hook handles the HTTP request to create a new post. The newPostMutation constant represents the mutation function and its configuration options.

The mutationFn is an asynchronous function that sends a POST request to the API endpoint. The request includes an object containing the title value from the post object.

To run the mutationFn, you will need to call the newPostMutation.mutate() method:

        const handleSubmit = async (event) => { 
  event.preventDefault();

  newPostMutation.mutate();
}

return (
    <form onSubmit={handleSubmit}>
      <input
type="text"
placeholder='Add Title'
name='title'
onChange={handleChange}
value={post.title}
/>
      <button>Add Post</button>
    </form>
  )
}

Submitting the form will run the handleSubmit function. The handleSubmit function is an asynchronous function that triggers the mutation function newPostMutation.mutate().

Efficient Data Fetching With Tanstack Query

This article explores how to handle data fetching in a React application using the tanstack/react-query library.

The tanstack/react-query library provides a powerful and flexible tool for fetching and caching data in React applications. It is easy to use, and its caching capabilities make it efficient and responsive.

Whether you are building a small personal project or an extensive enterprise application, the tanstack/react-query library can help you manage and display data effectively and efficiently. Along with React, Next.js also provides several built-in processes and third-party libraries to handle data fetching.