Files
gh-jezweb-claude-skills-ski…/references/v4-to-v5-migration.md
2025-11-30 08:25:35 +08:00

4.3 KiB

TanStack Query v4 to v5 Migration Guide

Complete migration checklist for upgrading from React Query v4 to TanStack Query v5


Breaking Changes Summary

1. Object Syntax Required ⚠️

v4 allowed multiple signatures:

useQuery(['todos'], fetchTodos, { staleTime: 5000 })
useQuery(['todos'], fetchTodos)
useQuery(queryOptions)

v5 only supports object syntax:

useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  staleTime: 5000
})

Migration: Use codemod or manual update

npx @tanstack/react-query-codemod v5/remove-overloads

2. Query Callbacks Removed ⚠️

Removed from queries (still work in mutations):

  • onSuccess
  • onError
  • onSettled

v4:

useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  onSuccess: (data) => console.log(data) // ❌ Removed
})

v5 - Use useEffect:

const { data } = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })

useEffect(() => {
  if (data) {
    console.log(data)
  }
}, [data])

Mutation callbacks still work:

useMutation({
  mutationFn: addTodo,
  onSuccess: () => {} // ✅ Still works
})

3. isLoadingisPending ⚠️

v4: isLoading meant "no data yet" v5: isPending means "no data yet", isLoading = isPending && isFetching

// v4
const { data, isLoading } = useQuery(...)
if (isLoading) return <Loading />

// v5
const { data, isPending } = useQuery(...)
if (isPending) return <Loading />

4. cacheTimegcTime ⚠️

// v4
cacheTime: 1000 * 60 * 60

// v5
gcTime: 1000 * 60 * 60

5. initialPageParam Required for Infinite Queries ⚠️

// v4
useInfiniteQuery({
  queryKey: ['projects'],
  queryFn: ({ pageParam = 0 }) => fetchProjects(pageParam),
  getNextPageParam: (lastPage) => lastPage.nextCursor,
})

// v5
useInfiniteQuery({
  queryKey: ['projects'],
  queryFn: ({ pageParam }) => fetchProjects(pageParam),
  initialPageParam: 0, // ✅ Required
  getNextPageParam: (lastPage) => lastPage.nextCursor,
})

6. keepPreviousDataplaceholderData ⚠️

// v4
keepPreviousData: true

// v5
import { keepPreviousData } from '@tanstack/react-query'

placeholderData: keepPreviousData

7. useErrorBoundarythrowOnError ⚠️

// v4
useErrorBoundary: true

// v5
throwOnError: true

// Or conditional:
throwOnError: (error) => error.status >= 500

8. Error Type Default Changed

v4: error: unknown v5: error: Error

If throwing non-Error types:

const { error } = useQuery<DataType, string>({
  queryKey: ['data'],
  queryFn: async () => {
    if (fail) throw 'custom string error'
    return data
  },
})

Step-by-Step Migration

Step 1: Update Packages

npm install @tanstack/react-query@latest
npm install -D @tanstack/react-query-devtools@latest

Step 2: Run Codemods

# Remove function overloads
npx @tanstack/react-query-codemod v5/remove-overloads

# Replace removed/renamed methods
npx @tanstack/react-query-codemod v5/rename-properties

Step 3: Manual Fixes

  1. Replace query callbacks with useEffect
  2. Replace isLoading with isPending
  3. Replace cacheTime with gcTime
  4. Add initialPageParam to infinite queries
  5. Replace keepPreviousData with placeholderData

Step 4: TypeScript Fixes

Update type imports:

// v4
import type { UseQueryResult } from 'react-query'

// v5
import type { UseQueryResult } from '@tanstack/react-query'

Step 5: Test Thoroughly

  • Check all queries work
  • Verify mutations invalidate correctly
  • Test error handling
  • Check infinite queries
  • Verify TypeScript types

Common Migration Issues

Issue: Callbacks not firing

Cause: Query callbacks removed Fix: Use useEffect or move to mutations

Issue: isLoading always false

Cause: Meaning changed Fix: Use isPending for initial load

Issue: cacheTime not recognized

Cause: Renamed Fix: Use gcTime

Issue: infinite query type error

Cause: initialPageParam required Fix: Add initialPageParam


Full Codemod List

# All v5 codemods
npx @tanstack/react-query-codemod v5/remove-overloads
npx @tanstack/react-query-codemod v5/rename-properties
npx @tanstack/react-query-codemod v5/replace-imports

Note: Codemods may not catch everything - manual review required!