Back to all posts

Getting Started with TanStack Query

Learn how to fetch and manage data in your React apps using TanStack Query

ReactTanStack QueryWeb Development

If you're tired of juggling useEffect, useState, and manual refetching logic—TanStack Query (aka React Query) might just be your new favorite tool. It’s built for React devs who want smooth, reliable data fetching with smart caching and fewer headaches.

Let's walk through the basics of setting it up and making your first query.

Why TanStack Query?

This library shines when you're dealing with:

  • REST or GraphQL APIs
  • Multiple loading states
  • Auto caching and refetching
  • Background updates (yep, it's magic)

If you've ever written the same useEffect + fetch + isLoading boilerplate in multiple components, you’ll love this.

Install It

First, install the core library:

npm install @tanstack/react-query

Set Up the Provider You'll need to wrap your app with QueryClientProvider:

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();

<QueryClientProvider client={queryClient}>
  <App />
</QueryClientProvider>;

Your First Query Let's say we're fetching users:

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

const fetchUsers = async () => {
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  if (!res.ok) throw new Error("Failed to fetch users");
  return res.json();
};

export function UsersList() {
  const { data, isLoading, isError, error } = useQuery({
    queryKey: ["users"],
    queryFn: fetchUsers,
  });

  if (isLoading) return <p>Loading users...</p>;
  if (isError) return <p>Error: {error.message}</p>;

  return (
    <ul>
      {data.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Mutations for POST, PUT, DELETE

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

const addUser = async (user) => {
  const res = await fetch("/api/users", {
    method: "POST",
    body: JSON.stringify(user),
    headers: { "Content-Type": "application/json" },
  });
  return res.json();
};

function AddUserForm() {
  const mutation = useMutation({ mutationFn: addUser });

  const handleSubmit = (e) => {
    e.preventDefault();
    const user = { name: "Sanjid" };
    mutation.mutate(user);
  };

  return (
    <>
      <form onSubmit={handleSubmit}>
        <button type="submit">Add User</button>
      </form>
      {mutation.isPending && <p>Sending...</p>}
      {mutation.isSuccess && <p>User added!</p>}
    </>
  );
}

Debugging Like a Pro Install Devtools for visual inspection of cache and query states:

npm install @tanstack/react-query-devtools
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";

<ReactQueryDevtools initialIsOpen={false} />;

Wrapping Up TanStack Query eliminates 90% of the boilerplate that comes with managing server data in React. It's my go-to in almost every project, especially when building dashboards or internal tools.

Once you start using it—you'll rarely look back.

Resources