Suggest an editImprove this articleRefine the answer for “What does React Query (TanStack Query) do?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**React Query (TanStack Query)** is a "smart server-data manager" for React that takes care of everything: fetching, caching, refetching, errors, synchronization, optimistic updates, and more. **Key point:** React Query doesn't replace Redux / Zustand, because it's not for client state (UI state), but for server state - data fetched from an API.Shown above the full answer for quick recall.Answer (EN)Image### Short answer: > **React Query (TanStack Query)** is a "smart server-data manager" for React, > which takes care of everything: loading, cache, refetch, errors, synchronization, optimistic updates, etc. > > It makes working with an API **reactive, fast, and safe**, > without manual `useEffect` and `useState`. ## What React Query (TanStack Query) does > **React Query is a "data client"**, > which manages *loading, caching, updating, and synchronizing* data in React apps. That is: - you describe **how to fetch the data (queryFn)** and **what this data is (queryKey)**, - and React Query itself: - makes the request; - caches the result; - updates the UI when the data changes; - revalidates the cache; - manages "loading", "error", and "stale" states; - syncs everything on window focus, tab switching, etc. --- ## In short: a **"Server state manager"** React Query doesn't replace Redux / Zustand, because **it's not for client state (UI state)**, but for **server state** - data fetched from an API. | Type of state | Example | Where to store it | |---|---|---| | *Client state* | modal open/closed, selected tab | useState / Redux / Zustand | | *Server state* | users, posts, orders, products | React Query | --- ## Example of basic usage ```javascript import { useQuery } from "@tanstack/react-query"; function UserProfile({ id }) { const { data, isLoading, error } = useQuery({ queryKey: ['user', id], queryFn: () => fetch(`/api/users/${id}`).then(res => res.json()), }); if (isLoading) return <p>Loading...</p>; if (error) return <p>Error loading user</p>; return <p>{data.name}</p>; } ``` React Query: - makes `fetch()` once; - caches the result under the key `['user', id]`; - if the component unmounts and appears again, **the data is already in the cache**, no new request needed; - if focus returns to the window, it **automatically refreshes the data**. --- ## Main features ### 1. **Data caching** React Query caches data in memory (`QueryClient`) with flexible settings: ```javascript <QueryClientProvider client={queryClient}> <App /> </QueryClientProvider> ``` Options: ```javascript useQuery({ staleTime: 5 * 60 * 1000, // considered fresh for 5 minutes cacheTime: 10 * 60 * 1000, // removed from memory after 10 min }); ``` --- ### 2. **Stale-While-Revalidate** Shows cached (stale) data **instantly**, while making a request for fresh data in parallel and **updating the UI afterward**. -> A UX with no loader "flicker". --- ### 3. **Refetch on focus / reconnect** If a user minimized a tab and then came back: - React Query automatically refetches data (if it's "stale"). ```javascript <QueryClientProvider client={new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: true } } })}> ``` --- ### 4. **Deduplication** If two components call the same query: ```javascript useQuery({ queryKey: ['user', 1], queryFn: fetchUser }); useQuery({ queryKey: ['user', 1], queryFn: fetchUser }); ``` React Query executes **only one request**, and both components receive the same data from the cache. --- ### 5. **Mutations (POST / PUT / PATCH / DELETE)** For changing data there's `useMutation()`: ```javascript import { useMutation, useQueryClient } from '@tanstack/react-query'; function UpdateUserButton({ id }) { const queryClient = useQueryClient(); const updateUser = useMutation({ mutationFn: (data) => fetch(`/api/users/${id}`, { method: 'PATCH', body: JSON.stringify(data), }), onSuccess: () => { // After a successful update, invalidate the cache queryClient.invalidateQueries(['user', id]); }, }); return ( <button onClick={() => updateUser.mutate({ name: 'Alex' })}> Update </button> ); } ``` --- ### 6. **Optimistic updates** Instantly updates the UI **before** the server responds, and rolls back on an error. ```javascript const mutation = useMutation({ mutationFn: likePost, onMutate: async (postId) => { await queryClient.cancelQueries(['post', postId]); const prev = queryClient.getQueryData(['post', postId]); queryClient.setQueryData(['post', postId], old => ({ ...old, likes: old.likes + 1 })); return { prev }; }, onError: (_, postId, ctx) => { queryClient.setQueryData(['post', postId], ctx.prev); }, onSettled: (postId) => { queryClient.invalidateQueries(['post', postId]); }, }); ``` --- ### 7. **Pagination, Infinite scroll, Prefetch** Built-in support for pagination and loading pages: ```javascript useInfiniteQuery({ queryKey: ['posts'], queryFn: ({ pageParam = 1 }) => fetch(`/api/posts?page=${pageParam}`).then(r => r.json()), getNextPageParam: (lastPage) => lastPage.nextPage, }); ``` --- ### 8. **Cache persistence** You can persist the cache across sessions: ```javascript import { persistQueryClient } from '@tanstack/react-query-persist-client'; persistQueryClient({ queryClient, persister: createSyncStoragePersister({ storage: window.localStorage }), }); ``` -> data isn't lost on reload, requests aren't repeated. --- ## What this looks like conceptually React Query takes care of: ```javascript manual fetch() useEffect() useState() loading / error / success state caching and invalidation repeated requests on focus all automatically ``` --- ## Key concepts | Term | What it is | |---|---| | **Query** | Reading data (GET) | | **Mutation** | Changing data (POST, PUT, DELETE) | | **Query Key** | A unique identifier for a query in the cache | | **Query Function** | The function that performs the request | | **Query Client** | The central cache manager | | **Invalidation** | Updating the cache after changes | | **Stale Time** | How long the data is considered fresh | | **Cache Time** | How long before the data is removed from memory | --- ## Summary | Capability | What React Query does | |---|---| | Automatic requests | makes and repeats fetches | | Caching | stores data by key | | Data refresh | refetch on focus/change | | State management | `isLoading`, `isError`, `isFetching`, `data` | | Optimistic updates | instant UI feedback | | Cache invalidation | refreshes after a `mutation` | | Deduplication | one request, many components | | Cache persistence | across tabs/sessions | | Infinite Scroll / Pagination | ready-made hooks | | No extra boilerplate | no useEffect/useState for requests |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.