Telerik blogs
ReactT2 Dark_1200x303

Let’s learn how to use React Query, which is a data-fetching library that uses a set of hooks to handle fetching for our React apps.

When we’re starting to learn React and how it works, we don’t see a problem with data fetching. Usually, our first React apps are simple apps where we’re not handling and we don’t need any data fetching.

Components play an important part in React applications because they are responsible for rendering content. We can create as many components as we want, and we can split a huge and messy component into small components and make our whole application more composable. But components are not responsible for fetching data from APIs. We need something else to help with that.

We have a lot of different ways of fetching data in React applications. We can use APIs and libraries that are widely used in React applications, such as the Fetch API, the Axios library, a custom React hook we can create ourselves, etc.

Every developer has a favorite method for fetching data, and choosing the right way can take time and discussion. Most of the time, fetching data can bring complexity to our code. Fetching data in modern React applications is a very important topic and that is what we’re going to learn more about today.

We’re going to learn about React Query and how the library is becoming one of the most standard ways for data fetching in React applications. It makes data fetching for React easy, powerful and fun.

React Query

Building custom React hooks for data fetching can be a good solution. We can create them the way we want them and use them whenever we want. A good point for not creating custom React hooks is that it requires a lot of time and testing, and you will need to support it now and then.

React Query is a data-fetching library for React applications that simplifies fetching data. It is a set of React hooks that help us improve the way we do data fetching in our applications. It can be customized as our application grows and has powerful features such as window refocus fetching, prefetching, optimistic updates, TypeScript support, React Suspense support, etc.

React Query makes fetching, caching, synchronizing, and updating server state in your React applications a breeze.React Query

It is very straightforward and simple to get started with React Query:

yarn add react-query

All we have to do is import the QueryClientProvider and QueryClient and do the following:

import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query-devtools";

const queryClient = new QueryClient({});

const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
      {/* The rest of your application */}
    </QueryClientProvider>
  );
};

export default App;

Debugging data fetching can be a pain and that’s why React Query comes with a dedicated devtools component.

import { ReactQueryDevtools } from 'react-query/devtools'

It will help you to understand and visualize how React Query fetches the data. It will save you hours of debugging and help you to check the current state of your requests.

import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";

const queryClient = new QueryClient({});

const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
      {/* The rest of your application */}
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  )
}

useQuery Hook

The useQuery hook handles fetching data and can be used with any promise-based method. Whenever you want to fetch some resource, you’re going to use the useQuery hook.

This hook accepts a unique key for the query and a function that returns a promise. The unique key is used for internally refetching, caching and sharing your query.

const result = useQuery(key, promiseBasedFn);

The object that the useQuery hook returns has some internal states that are very helpful, such as isLoading, isError, isSuccess, isSuccess, error, data, isFetching.

Let’s create a simple example using the useQuery hook. We’re going to use the Chuck Norris API for fetching a random chuck joke.

We’re going to install Axios to use it as our promise-based function to fetch our data.

yarn add axios

Now, we’re going to create a component called Joke. Inside this component, we’re going to use the useQuery hook for fetching a random chuck joke.

import React from "react";

cont Joke = () => {
  return (
    ...
  )
};

export default Joke;

The first thing we’re going to do is pass a unique key to the useQuery hook, which we’re going to call joke.

As a second argument, we’re going to pass the promise-based function for fetching our data and this is where we’re going to use Axios. We’re going to create a simple async/await function and return our data.

import React from "react";
import axios from "axios";
import { useQuery } from "react-query";

cont Joke = () => {
  const result = useQuery(
    "joke",
    async () => {
      const { data } = await axios("https://api.chucknorris.io/jokes/random");
      return data;
    }
  );

  return (
    ...
  )
};

export default Joke;

We’re going to use object destructuring to destructure our object response and use some properties on our component. We’re going to render a simple h1 element for showing our joke and a button to refetch a new joke.

import React from "react";
import axios from "axios";
import { useQuery } from "react-query";

const Joke = () => {
  const { isLoading, isError, data, error, refetch } = useQuery(
    "joke",
    async () => {
      const { data } = await axios("https://api.chucknorris.io/jokes/random");
      return data;
    }
  );

  if (isLoading) {
    return <h1>Loading...</h1>;
  }

  if (isError) {
    return <h1>{error}</h1>;
  }

  return (
    <>
      <h1>{data.value}</h1>
      <button type="button" onClick={refetch}>
        Another joke
      </button>
    </>
  );
};

export default Joke;

The refetch function is very helpful for manually fetching the query.

You can check out all the options and returned values that the useQuery hook accepts here. There are plenty more examples that we could build and the documentation is very helpful for it. One of the best is the Suspense example, showing how easy it is to use the useQuery hook with React Suspense.

useMutation Hook

The useMutation hook handles side effects on the server. Whenever you need to perform something—like create, update or delete a resource on the server—the useMutation hook is the right hook for it.

The useMutation hook is very similar to the useQuery hook, but instead of receiving two arguments, it receives only one. It receives a callback function that returns a promise and performs an asynchronous task on the server.

const mutation = useMutation((variables) => promiseBasedFn);

A good way to debug your function on the React Query devtools is to pass an object as a second argument. Inside this object, you can pass a mutation key, and a few more functions such as onError, onSuccess, onMutate, onSettled and useErrorBoundary.

const mutation = useMutation((variables) => promiseBasedFn, { 
  onError,
  onSuccess,
  onMutate,
  onSettled,
  useErrorBoundary
});

Conclusion

Since React hooks were released, data fetching in React is becoming easier. We can split our data fetching logic in custom React hooks and make our applications more composable by default.

React Query comes to brings a set of powerful React hooks for data fetching in React applications. It comes with many features out of the box that help us to take care of what data to fetch instead of how we are going to fetch a resource on our server.


Leonardo Maldonado
About the Author

Leonardo Maldonado

Leonardo is a full-stack developer, working with everything React-related, and loves to write about React and GraphQL to help developers. He also created the 33 JavaScript Concepts.

Related Posts

Comments

Comments are disabled in preview mode.