All Resources
Guide
ReactData FetchingState Management
June 8, 2024

React Query Advanced Patterns

Advanced data synchronization patterns with React Query (TanStack Query).

Overview

React Query (now TanStack Query) is a powerful library for managing server state. Learn advanced patterns for complex data synchronization scenarios.

Key Concepts

  • Query Keys: Organize and invalidate queries
  • Background Refetching: Keep data fresh automatically
  • Optimistic Updates: Instant UI feedback
  • Pagination: Handle large datasets efficiently
  • Mutations: Coordinate updates with queries

Setup

npm install @tanstack/react-query

Query Keys Strategy

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

// Good query keys
const queryKeys = {
  all: ['users'],
  lists: () => [...queryKeys.all, 'list'],
  list: (filters: Filters) => [...queryKeys.lists(), { filters }],
  details: () => [...queryKeys.all, 'detail'],
  detail: (id: number) => [...queryKeys.details(), id]
}

const { data } = useQuery({
  queryKey: queryKeys.detail(123),
  queryFn: () => fetchUser(123)
})

Optimistic Updates

const mutation = useMutation({
  mutationFn: (newName: string) => updateUser(123, { name: newName }),
  onMutate: async (newName) => {
    await queryClient.cancelQueries({ queryKey: queryKeys.detail(123) })
    
    // Store previous data
    const previous = queryClient.getQueryData(queryKeys.detail(123))
    
    // Optimistically update cache
    queryClient.setQueryData(queryKeys.detail(123), (old) => ({
      ...old,
      name: newName
    }))
    
    return { previous }
  },
  onError: (err, newName, context) => {
    // Revert on error
    queryClient.setQueryData(queryKeys.detail(123), context?.previous)
  },
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: queryKeys.detail(123) })
  }
})

Infinite Queries

const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
  queryKey: ['posts'],
  queryFn: ({ pageParam = 0 }) => fetchPosts(pageParam),
  getNextPageParam: (lastPage) => lastPage.nextCursor
})

return (
  <>
    {data?.pages.map((page) =>
      page.posts.map((post) => <Post key={post.id} {...post} />)
    )}
    {hasNextPage && (
      <button onClick={() => fetchNextPage()}>Load more</button>
    )}
  </>
)

React Query reduces boilerplate for server state by 80% compared to useState/useEffect.

Curated by

Shyam