SWR vs TanStack Query: Choosing a React Data Library

Compare SWR and TanStack Query for React data fetching. Learn the differences in caching, mutations, and devtools, and which library fits your app.

7 min read

SWR and TanStack Query both cache and deduplicate requests in React, but they differ in size and scope. SWR is minimal and focused on stale-while-revalidate fetching, while TanStack Query adds mutations, devtools, and more granular cache controls. This guide compares them side by side.

The core difference in a table

The libraries solve the same problem with different scopes. SWR stays small and centers on the fetch, while TanStack Query is a broader toolkit that also handles writes.

FeatureSWRTanStack Query
Packageswr@tanstack/react-query
Core hookuseSWR(key, fetcher)useQuery({ queryKey, queryFn })
Mutationsglobal mutate helperuseMutation and invalidateQueries
Devtoolsnone built inofficial devtools package
Cache optionsdedupingInterval, revalidate flagsstaleTime, gcTime, retry

The table shows the main gap. SWR has no built-in mutation hook, while TanStack Query treats queries and mutations as first-class concepts.

For a read-only dashboard that gap barely matters, and for an app that writes data often it is the deciding factor. The tradeoff is size and surface area: SWR gives you less to learn, and TanStack Query gives you more built-in answers.

How the basic query compares

For a plain read, the code looks nearly identical. SWR takes a key string and a fetcher function, while TanStack Query takes an options object with a key array and a query function.

App.jsxApp.jsx
import useSWR from "swr";
 
function Posts() {
  const { data, error, isLoading } = useSWR("/api/posts", fetcher);
  if (isLoading) return <p>Loading posts...</p>;
  if (error) return <p>Could not load posts.</p>;
  return <ul>{data.map((post) => <li key={post.id}>{post.title}</li>)}</ul>;
}

The fetcher is any function that returns JSON, usually a wrapper around fetch. SWR returns data, error, and isLoading, and it deduplicates requests that use the same key automatically. The page also revalidates on focus and reconnect, which is the behavior the name describes.

App.jsxApp.jsx
import { useQuery } from "@tanstack/react-query";
 
function Posts() {
  const { isPending, isError, data, error } = useQuery({
    queryKey: ["posts"],
    queryFn: fetchPosts,
  });
  if (isPending) return <p>Loading posts...</p>;
  if (isError) return <p>Could not load posts: {error.message}</p>;
  return <ul>{data.map((post) => <li key={post.id}>{post.title}</li>)}</ul>;
}

TanStack Query returns the same three concepts under different names: isPending for the first load, isError, and data. The key is an array rather than a string, which allows more structure. The query key is explained in useQuery explained.

What TanStack Query adds

TanStack Query's extra surface shows up when the app grows. It ships a mutation hook for writes, official devtools, and more granular options such as staleTime and gcTime.

  • useMutation and invalidateQueries handle writes and the refetch that follows.
  • The devtools let you inspect and edit the cache while developing.
  • staleTime and gcTime tune freshness and memory separately.
  • Retry, pagination, and infinite query helpers are built in.

SWR covers reads very well and leaves writes to your own functions or its global mutate helper. Both libraries share the same stale-while-revalidate idea, so the mental model carries over.

None of these extras are missing from SWR by accident; they are simply outside its minimal scope. The TanStack setup behind those features is covered in how to set up TanStack Query in React.

Which should you choose?

Choose SWR when the app is mostly reads and you want a small, focused dependency. Choose TanStack Query when writes, devtools, and fine-grained cache control are part of the job.

A read-heavy dashboard with a few endpoints is a strong fit for SWR. An app with forms, optimistic updates, and many related endpoints is a stronger fit for TanStack Query.

For one or two requests on a page, neither library is required; plain state or a custom Hook is enough. The libraries earn their place once several components share the same data.

SWR also has a smaller API to learn, which matters for a small team moving fast. If you already use one and it covers your cases, switching is rarely worth it. Both replace the manual Effect fetch described in how to fetch API data in React.

Rune AI

Rune AI

Key Insights

  • SWR is minimal; TanStack Query is a larger toolkit.
  • Both dedupe and cache by key.
  • SWR uses useSWR, TanStack Query uses useQuery.
  • TanStack Query adds useMutation and devtools.
  • Choose by writes and cache-control needs.
RunePowered by Rune AI

Frequently Asked Questions

Which is smaller, SWR or TanStack Query?

SWR is the smaller, more focused library. TanStack Query is larger because it bundles mutations, devtools, and more cache and retry options.

Does SWR have mutations?

Not a mutation hook like useMutation. SWR relies on your own write functions plus its global mutate helper, while TanStack Query has useMutation and invalidateQueries.

Can I switch between the two later?

The concepts transfer, because both use stale-while-revalidate and keyed caching. The code differs, but the mental model is the same.

Conclusion

SWR is the small, read-focused option, and TanStack Query is the broader toolkit with mutations, devtools, and fine-grained cache control. Pick SWR for simple reads and TanStack Query when writes and cache tuning matter.