Do you know the best libraries to fetch data in React?

Last updated by Jeoffrey Fischer [SSW] 3 months ago.See history

While using a regular useEffect to run when a component is loaded to fetch data is super easy, it may result in unnecesary duplicate requests for data or unexpected errors when unmounting components. It is best to use a library that can provide hooks for fetching data, as not only does it solve the above issues, but also comes with useful features such as caching, background updates, and pre-fetching.

Below is an example of a standard data fetch in React:

const Component = () => {
  const [data, setData] = useState({});
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/todos/1")
      .then(res => res.json())
      .then(json => {
        setData(json);
        setLoading(false);
      })
  }, [])

  return (
    {loading
      ? <> {/* Display data here */} </>
      : <p>Loading...</p>
    }
  )
}

Figure: The traditional way of fetching data in React

This example is not ideal, as it means every time we reload this page component, or if we make the same request on another page, there will be an unnecessary request made instead of pulling the data from a cache.

Below are the two recommended options that both serve effectively the same purpose in providing developers with useful hooks for fetching data. These libraries not only give developers a wide range of other features, but also reduces the amount of boilerplate code they have to write.

TanStack Query is a feature-rich data fetching library developed by Tanstack. It can be used with existing data fetching libraries such as Axios, GraphQL packages such as graphql-request, or just plain fetch.

Video: React Query in 100 Seconds by Fireship (2 mins)

Here's a basic example of how you can use Tanstack Query:

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

const queryClient = new QueryClient();

function useTodos() {
  return useQuery("todos", async () => {
    const res = await fetch("/api/todos");
    const json = await res.json();
    return json;
  })
}

export const Page = () => {
  const { status, data, error, isFetching } = useTodos();

  if (status === "error") return <div>Error loading data: {error}</div>
  if (status === "loading") return <div>Loading...</div>

  return (
    <QueryClientProvider client={queryClient}>
      <div>
        <div>{/* Display todos here */}</div>
        {isFetching && <p>Re-fetching data in the background...</p>}
      </div>
    </QueryClientProvider>
}

This code employs the useQuery hook for asynchronous data fetching and a QueryClientProvider to manage the query cache in the component tree.

Some features of Tanstack Query:

You can find out more about Tanstack Query at tanstack.com/query.

SWR

SWR is an alternative to Tanstack Query developed by Vercel, the team behind Next.js. Much like Tanstack Query, SWR is library-agnostic, meaning you can use whatever data fetching library you are comfortable with.

Here's a basic example of how you can use the library's fetching hook:

const fetcher = (url) => fetch(url).then(res => res.json())

export const Page = () => {
  const { data, error, isLoading } = useSWR("/api/todos", fetcher);

  if (error) return <div>Error loading data</div>
  if (loading) return <div>Loading...</div>

  return <div>{/* Display todos here */}</div>
}

Some features of SWR:

Note: Currently, the vast majority of SWR APIs are not compatible with the App router in Next.js 13.

You can find out more about using SWR at swr.vercel.app.

RTK Query

Additionally, RTK Query, part of the Redux Toolkit, is a similar library to SWR and React Query with tight integration with Redux and seamless type-safe importing sourced from OpenAPI specifications.

Here's a basic example of how you can use RTK Query:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const todosApi = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (builder) => ({
    getTodos: builder.query<Array<Todo>, void>({
      query: () => 'todos',
    }),
  }),
});

const { useGetTodosQuery } = todosApi;

// For use with Redux
const todosApiReducer = todosApi.reducer;

const TodoPage = () => {
  const { data, isError, isLoading } = useGetTodosQuery();

  if (isLoading) return <p>Loading...</p>;
  if (isError) return <p>Error fetching todos</p>;

  return (
    <div>{/*( Display todos here */}</div>
  );
};

Some features of RTK Query:

  • Seamless Redux integration: Designed as part of the Redux Toolkit, RTK Query is intrinsically designed to work with Redux, providing a cohesive data management experience. Learn more
  • OpenAPI schema code generation: Auto-generates end-to-end typed APIs based on OpenAPI schemas, drastically reducing boilerplate and ensuring type safety. Learn more
  • Caching - cache management based on endpoint and serialized arguments - learn more
  • Automatic retries - built-in mechanism to automatically retry failed queries, enhancing resilience - learn more
  • Prefetching - fetches data in anticipation of user actions to enhance UX - learn more
  • Parallel and dependent queries: Efficient handling of multiple simultaneous or dependent data fetching. Learn more

Discover more about RTK Query in Redux Toolkit's official documentation at redux-toolkit.js.org/rtk-query/overview.

We open source. Powered by GitHub