TanStack Query
Server state management: queries, mutations, caching, pagination, optimistic updates.
reactdata-fetchingfrontend
# TanStack Query
## Install
```bash
npm install @tanstack/react-query
```
## Setup
```tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const queryClient = new QueryClient({
defaultOptions: { queries: { staleTime: 1000 * 60 } },
})
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
```
## useQuery
```tsx
const { data, isLoading, isError, error, refetch } = useQuery({
queryKey: ['users', userId], // cache key
queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json()),
staleTime: 1000 * 60 * 5, // fresh for 5 min
gcTime: 1000 * 60 * 10, // cache 10 min after last use
enabled: !!userId, // conditional fetch
retry: 3,
select: (data) => data.users, // transform
})
```
## useMutation
```tsx
const mutation = useMutation({
mutationFn: (newUser) => fetch('/api/users', {
method: 'POST', body: JSON.stringify(newUser),
}).then(r => r.json()),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] })
},
onError: (error) => console.error(error),
})
mutation.mutate({ name: 'Alice' })
// or async:
await mutation.mutateAsync({ name: 'Bob' })
```
## Optimistic updates
```tsx
onMutate: async (newUser) => {
await queryClient.cancelQueries({ queryKey: ['users'] })
const previous = queryClient.getQueryData(['users'])
queryClient.setQueryData(['users'], (old) => [...old, newUser])
return { previous } // rollback context
},
onError: (err, vars, ctx) => {
queryClient.setQueryData(['users'], ctx.previous)
},
```
## Pagination
```tsx
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
queryKey: ['posts'],
queryFn: ({ pageParam = 1 }) => fetchPosts(pageParam),
getNextPageParam: (lastPage) => lastPage.nextCursor,
})
// data.pages is array of pages; data.pages.flatMap(p => p.items)
```
## Prefetch
```tsx
await queryClient.prefetchQuery({
queryKey: ['user', id],
queryFn: () => fetchUser(id),
})
// Next.js: call in Server Component, pass dehydrated state to client
```
## DevTools
```tsx
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
<ReactQueryDevtools initialIsOpen={false} />
```API: /api/skills/tanstack-query