How to auto-pull data in React-Query

Introduction

React-Query is a powerful tool for fetching/caching the data on the frontend side, yet working with React-Query might be a bit not straightforward, in this article we’re going to see how we can implement a functionality to auto-pull or refetch the data each X time from the backend.

Let’s get started!

auto-pull or refetching or real-time fetching

To achieve auto-pulling or refetching or real-time fetching data from the backend using React-Query, we’re going to implement a tiny Todo app, in which the user can enter his to-do list, then submit the to-do item to the server. At the same time, we will add the functionality to pull the data from the backend each X time. By this, we will be able to achieve the goal of implementing auto-pull data using React-Query.

Full example source code

For this article, we will use the NextJS starter kit by stackBlitz, and we will implement a small endpoint that simulates adding/retrieving the to-do list items.

Backend Side

The following code implementation is sitting under src/pages/api/data.js file.

// A simple endpoint for getting current todo list
let list = ['Item 1', 'Item 2', 'Item 3'];

export default async (req, res) => {
  if (req.query.add) {
    if (!list.includes(req.query.add)) {
      list.push(req.query.add);
    }
  } else if (req.query.clear) {
    list = [];
  }

  await new Promise((r) => setTimeout(r, 500));

  res.json(list);
}

We have a predefined list of to-do items on line 2.

Then, we’ve two statement checks, we will rely on the first one if (req.query.add) to add new to-do items,

and on the 2nd one if (req.query.clear) to clear the to-do list items and return an empty list.

In line 12, we’re adding a time delay of 500ms to simulate that the request is taking some time in processing.


Frontend Side

On the front end side, we need to create a single file src/pages/index.js that will have the implementation of our React-Query component and the wrapper component.

First, let’s create our wrapper component <App> inside the file:

import React from 'react';
import axios from 'axios';
import {
  useQuery,
  useQueryClient,
  useMutation,
  QueryClient,
  QueryClientProvider,
} from '@tanstack/react-query';

const queryClient = new QueryClient();

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Example />
    </QueryClientProvider>
  );
}

As shown above, we’ve added imports for React, Axios, and some other React-Query functionalities.

Then we’ve initialized a new QueryClient const queryClient = new QueryClient();, we will use this to pass it as a prop to the QueryClientProvider as shown in line 15.


Now, let’s add the implementation for the <Example> component:

function Example() {
  const queryClient = useQueryClient();
  const [value, setValue] = React.useState('');

  const { status, data, error } = useQuery(
    ['todos'],
    async () => {
      const res = await axios.get('/api/data');
      return res.data;
    },
    {
      // Refetch the data every 1 second = 1000 ms
      refetchInterval: 1000,
    }
  );

  const addMutation = useMutation((value) => fetch(`/api/data?add=${value}`), {
    onSuccess: () => queryClient.invalidateQueries(['todos']),
  });

  const clearMutation = useMutation(() => fetch(`/api/data?clear=1`), {
    onSuccess: () => queryClient.invalidateQueries(['todos']),
  });

  if (status === 'loading') return <h1>Loading...</h1>;
  if (status === 'error') return <span>Error: {error.message}</span>;

  return (
    <div>
      <h1>Auto Refetch/Auto Pulling</h1>
      <h2>Todo List</h2>
      <form
        onSubmit={(event) => {
          event.preventDefault();
          addMutation.mutate(value, {
            onSuccess: () => {
              setValue('');
            },
          });
        }}
      >
        <input
          placeholder="Enter item"
          value={value}
          onChange={(ev) => setValue(ev.target.value)}
        />
        <div style={{ marginTop: '10px', width: '150px' }}>
          <button type="submit" style={{ width: '100%' }}>
            Add
          </button>
        </div>
      </form>
      <ul>
        {data.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
      <div>
        <button
          onClick={() => {
            clearMutation.mutate();
          }}
        >
          Clear All
        </button>
      </div>
    </div>
  );
}

Fetch Query (auto-pull)

At line2, we’ve created a new instance on queryClient, and this will be used to call the invalidateQueries method over the todos query, once the user added a new to-do item or once he cleared the list of the items.

In line3, we’ve created a new state variable value which will hold the new to-do item the user entered in the input field. Then we will use this value in submitting the form (line35).

In line5, we’ve added the implementation of the todos query, which has the following properties:

  • queryKey ['todos'].
  • the async function that uses axios to call the backend endpoint api/data to fetch the to-do list.
  • refetchInterval which is set to 1000ms for now, and this value will tell React-Query to auto-pull the data (i.e: execute the query) every 1000ms.

Submit/Mutate Queries

In line17, we’ve hooked up useMutation with the `/api/data?add=${value}` backend API and we will use the mutate function in order to submit the data to the backend.

Once the submit request succeeded (onSuccess), we will invalidate the query (a new request will be sent to the backend to fetch the latest list of the to-do items).

queryClient.invalidateQueries(['todos'])

In line21, we’ve used the useMutation hook in the same way as we did in line17, the only difference here is that we’re using this request to clear the data from the backend. And on the request success response, we do invalidate the query again.


Component render implementation

Inside the component render method, we’ve created a simple form with one input field and two buttons. A submit button to submit the form, and a clear button to clear the to-do list items.


Testing the implementation

Now try to open the app in the browser, you should be able to see the following page:

React-Query auto-pull example
React-Query auto-pull example

Trying to add a new to-do item should work fine without any issues, as shown below.

React-Query auto-pull example
React-Query auto-pull example

That’s awesome! But how we can make sure that the auto-pulling or refetching is working as expected?

A simple way to do that, we can open the link in two different tabs, and try to submit the data from one tab, you should be able to see it gets updated in the 2nd tab after 1000ms, also when trying to clear the list in one tab, we also should be able to see the list clear in the 2nd tab as well after 1000ms. Let’s check that out.

React-Query auto-pull example
React-Query auto-pull example

that’s it for How to auto-pull data in React-Query, And as always happy coding!

Full example source code

Photo from unsplash

Related Posts

How to remove highcharts.com credits link

How to remove highcharts.com credits link

Highcharts is a popular JavaScript charting library that offers a wide range of interactive and customizable charts for developers. However, if you’re using the free version of…

Highcharts Place text in the center of a pie chart

Highcharts Place text in the center of a pie chart

To place text in the center of a pie chart in Highcharts, you can use the chart.renderer object to create a custom label and position it in…

Test design breakpoints using jest and react-testing-library

Test responsive design using jest and react-testing-library

Testing design breakpoints in React applications is an important aspect of front-end development. It ensures that the components look and behave as expected on different screen sizes….

Testing React-Query with Jest and React-testing-library

Testing React-Query with Jest and React-testing-library

Introduction In this article we will cover the basic usage of testing useQuery hook from tanstack/react-query library, along with how to test it using jest and react-testing-library….

Highcharts How To Change Series Color with examples

Highcharts How To Change Series Color with examples

To change the color of a series in Highcharts, there are a set of options we are going to discover in this article. Option 1: Using the…

A quick introduction to Javascript shadow DOM

A quick introduction to Javascript shadow DOM

Introduction JavaScript Shadow DOM is a powerful tool for creating isolated and reusable components in web development. It allows developers to create custom elements with their own…

Leave a Reply

%d bloggers like this: