Back to articles

Modern React Data Fetching: Goodbye useEffect, Hello React Query/TanStack Query

AuthorMajd Muhtaseb04/28/20257 minutes
Modern React Data Fetching: Goodbye useEffect, Hello React Query/TanStack Query

The Problem with useEffect for Data Fetching

For years, useEffect has been the go-to hook for fetching data in React components. While functional, it often leads to verbose and complex code, especially when handling caching, error states, and background updates. Here's a typical, simplified example:

import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      setIsLoading(true);
      try {
        const response = await fetch(`/api/users/${userId}`);
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
        const data = await response.json();
        setUser(data);
      } catch (error) {
        setError(error);
      } finally {
        setIsLoading(false);
      }
    }

    fetchData();
  }, [userId]);

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!user) return <p>No user found.</p>;

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
    </div>
  );
}

export default UserProfile;

This simple example quickly becomes unwieldy with more complex requirements like pagination, optimistic updates, and server-side rendering.

Enter React Query (TanStack Query)

React Query (now known as TanStack Query) provides a powerful and elegant solution for managing server state in your React applications. It handles caching, background updates, retries, and more, significantly reducing boilerplate code.

A Simple Example with React Query

First, install the library:

npm install @tanstack/react-query

Now, let's rewrite the UserProfile component using TanStack Query:

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

async function fetchUser(userId) {
  const response = await fetch(`/api/users/${userId}`);
  if (!response.ok) {
    throw new Error(`HTTP error! Status: ${response.status}`);
  }
  return response.json();
}

function UserProfile({ userId }) {
  const { data: user, isLoading, error } = useQuery({
    queryKey: ['user', userId],
    queryFn: () => fetchUser(userId),
  });

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!user) return <p>No user found.</p>;

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
    </div>
  );
}

export default UserProfile;

Key improvements:

  • Conciseness: The code is much cleaner and easier to read.
  • Caching: React Query automatically caches the fetched data. Subsequent requests for the same user will be served from the cache, improving performance.
  • Background Updates: React Query can automatically refetch data in the background, ensuring your UI is always up-to-date.
  • Error Handling: Error handling is simplified and centralized.
  • Automatic Retries: React Query can automatically retry failed requests.
  • Devtools: TanStack Query provides a fantastic devtools extension for inspecting your queries and mutations.

Beyond the Basics

React Query offers a wide range of features, including:

  • Mutations: For handling updates, creates, and deletes.
  • Pagination and Infinite Queries: Efficiently manage large datasets.
  • Optimistic Updates: Improve the user experience by immediately updating the UI before the server confirms the change.
  • Server-Side Rendering (SSR) Support: Seamless integration with SSR frameworks.

Conclusion

React Query (TanStack Query) significantly simplifies data fetching in React applications. By abstracting away the complexities of caching, background updates, and error handling, it allows you to focus on building user interfaces. Make the switch and experience a more maintainable and performant data fetching solution.