Codemods and Migration Tools

Purpose and Scope

This page explains the migration tooling that exists in the TanStack Query repository and how to use it safely during major-version upgrades. A codemod is an automated source transform, typically run with jscodeshift, that rewrites recognizable code patterns for a breaking change. In this repository, codemods are positioned as migration helpers rather than complete upgrade engines: they can handle common syntax changes, but the migration guides repeatedly tell users to review the generated code, inspect logs, and finish any edge cases manually.

Sources: packages/query-codemods/package.json, docs/framework/react/guides/migrating-to-v5.md, docs/framework/react/guides/migrating-to-react-query-4.md

The main migration story covered here is the React adapter upgrade path from older React Query APIs to TanStack Query v4 and v5. v4 introduced package and import changes, plus array-only query and mutation keys. v5 removed the old overloaded call signatures for hooks and many QueryClient methods in favor of a single object signature. The repository also contains a focused v5 codemod note for the keepPreviousData migration, which documents what shape of code the transform can and cannot modify automatically.

Sources: packages/query-codemods/src/v5/keep-previous-data/README.md, docs/framework/react/guides/migrating-to-v5.md, docs/framework/react/guides/migrating-to-react-query-4.md

Relevant Source Files

  • packages/query-codemods/package.json - Defines the private @tanstack/query-codemods workspace package, describes it as a collection of codemods to make migration easier, and records its jscodeshift development dependency and test scripts.
  • packages/query-codemods/src/v5/keep-previous-data/README.md - Documents the v5 keepPreviousData transform prerequisites, affected usage shape, a non-transformed identifier example, and troubleshooting guidance.
  • docs/framework/react/guides/migrating-to-v5.md - Provides the official v5 breaking-change guide, including the move to one object signature for hooks, query client methods, query cache methods, and a codemod warning for the overload-removal migration.
  • docs/framework/react/guides/migrating-to-react-query-4.md - Provides the official v4 migration guide, including import replacement commands, key transformation commands, parser requirements, and post-codemod formatting notes.

Migration Strategy

Treat the migration guides as the source of truth for sequencing and the codemods as accelerators for repetitive edits. For v4, start by changing package dependencies from react-query to @tanstack/react-query and installing the separate devtools package when your application uses devtools. Then run the import codemod to rewrite imports from the old package names. After that, address the query-key breaking change by converting string keys to array keys, either manually or with the key transformation codemod.

Sources: docs/framework/react/guides/migrating-to-react-query-4.md

For v5, the largest source-level shift is the removal of overloads. Older calls such as useQuery(key, fn, options), useMutation(fn, options), and queryClient.fetchQuery(key, fn, options) become object-form calls such as useQuery({ queryKey, queryFn, ...options }), useMutation({ mutationFn, ...options }), and queryClient.fetchQuery({ queryKey, queryFn, ...options }). Filters also move into object arguments, for example queryClient.invalidateQueries({ queryKey, ...filters }). That consistency removes runtime signature detection and makes the public API easier to type and maintain.

Sources: docs/framework/react/guides/migrating-to-v5.md

A practical upgrade should be staged. First, make sure your code compiles on the source version and commit a clean baseline. Second, apply the version-specific codemod to a narrow directory, not the whole repository, so diffs are reviewable. Third, run formatting and linting, because the v4 guide explicitly notes that codemods can disturb formatting. Finally, run type checks and application tests to find patterns the transform could not safely infer, such as options objects stored in variables or custom wrappers around the public hooks.

Sources: docs/framework/react/guides/migrating-to-react-query-4.md, packages/query-codemods/src/v5/keep-previous-data/README.md

v4 Codemods

The v4 guide documents two concrete transforms. The first changes imports from react-query and react-query/devtools to @tanstack/react-query and @tanstack/react-query-devtools. This is intentionally limited to import rewriting; the guide states that installing the separate devtools package remains a manual dependency-management step. Run the JavaScript transform with --extensions=js,jsx, or run the TypeScript transform with --extensions=ts,tsx and --parser=tsx. The parser note matters because TypeScript syntax will not be rewritten reliably with the wrong parser.

Sources: docs/framework/react/guides/migrating-to-react-query-4.md

npx jscodeshift ./path/to/src/ \
  --extensions=js,jsx \
  --transform=./node_modules/@tanstack/react-query/codemods/v4/replace-import-specifier.js
 
npx jscodeshift ./path/to/src/ \
  --extensions=ts,tsx \
  --parser=tsx \
  --transform=./node_modules/@tanstack/react-query/codemods/v4/replace-import-specifier.js

The second v4 transform handles query-key and mutation-key shape. v3 allowed strings in many places, but the v4 guide explains that TanStack Query standardized keys as arrays. This makes APIs more consistent because internals and callback contexts already operated around array keys in important places. The documented codemod transforms common key usages, but it should still be followed by review, especially where keys are assembled dynamically, passed through helper functions, or inspected by predicates and global callbacks.

Sources: docs/framework/react/guides/migrating-to-react-query-4.md

npx jscodeshift ./path/to/src/ \
  --extensions=js,jsx \
  --transform=./node_modules/@tanstack/react-query/codemods/v4/key-transformation.js
 
npx jscodeshift ./path/to/src/ \
  --extensions=ts,tsx \
  --parser=tsx \
  --transform=./node_modules/@tanstack/react-query/codemods/v4/key-transformation.js

v5 Codemods and Object Signatures

The v5 migration guide frames overload removal as a major API simplification. Instead of supporting many call signatures for every hook and cache method, the API accepts one object shape. That affects useQuery, useInfiniteQuery, useMutation, useIsFetching, useIsMutating, and many QueryClient methods including isFetching, ensureQueryData, getQueriesData, setQueriesData, removeQueries, resetQueries, cancelQueries, invalidateQueries, refetchQueries, fetchQuery, prefetchQuery, fetchInfiniteQuery, and prefetchInfiniteQuery. It also affects query cache lookups such as queryCache.find and queryCache.findAll.

Sources: docs/framework/react/guides/migrating-to-v5.md

useQuery(key, fn, options)
useQuery({ queryKey, queryFn, ...options })
 
queryClient.invalidateQueries(key, filters, options)
queryClient.invalidateQueries({ queryKey, ...filters }, options)
 
queryCache.find(key, filters)
queryCache.find({ queryKey, ...filters })

The repository’s keepPreviousData v5 codemod README adds an important constraint that applies to automated transforms generally: the transform only rewrites usages where the first argument is an object expression. A direct call like useQuery({ queryKey: ['posts'], queryFn, keepPreviousData: true }) is in the supported shape. A call like useQuery(hookArgument), where the options object is stored in an identifier, is not transformed by that codemod. That limitation is deliberate because following arbitrary identifiers safely would require broader program analysis and could produce incorrect edits.

Sources: packages/query-codemods/src/v5/keep-previous-data/README.md

const { data } = useQuery({
  queryKey: ['posts'],
  queryFn: queryFn,
  keepPreviousData: true,
})
 
const hookArgument = {
  queryKey: ['posts'],
  queryFn: queryFn,
  keepPreviousData: true,
}
const { data } = useQuery(hookArgument)

Tooling Package Reference

@tanstack/query-codemods is represented as a private workspace package rather than a normal public runtime dependency. Its package description is explicit: it is a collection of codemods to make migration easier. The package is an ES module package, declares sideEffects: false, and includes source files while excluding tests and fixtures from its file list. Its development dependencies include jscodeshift and @types/jscodeshift, which matches the command-line usage documented in the migration guides.

Sources: packages/query-codemods/package.json

AreaSource-backed detail
Package name@tanstack/query-codemods
Package roleCollection of migration codemods
Runtime statusPrivate workspace package
Transform runnerjscodeshift development dependency
Local testsvitest via test:lib and ESLint via test:eslint
Published files intentsrc included, tests and fixtures excluded

The package-level scripts show how maintainers validate the codemod workspace: test:eslint runs ESLint over ./src, test:lib runs Vitest, and test:lib:dev runs Vitest in watch mode. For application developers, those scripts are less important than the migration-guide commands, but they show the expected implementation environment. If you are contributing a new transform or fixing an edge case, use the package scripts to validate behavior before proposing changes.

Sources: packages/query-codemods/package.json

Review Checklist and Troubleshooting

Every codemod documented in these migration guides carries the same operational warning: it is a best-efforts attempt. Review generated code thoroughly, watch command output for edge cases, and do not assume the transform has understood custom abstractions. The keepPreviousData README asks users who hit errors to contact the project via Discord or open an issue, and it specifically asks for a code snippet. That request is practical: source transforms fail on concrete syntax shapes, and maintainers need a minimal example to reproduce the AST pattern.

Sources: packages/query-codemods/src/v5/keep-previous-data/README.md, docs/framework/react/guides/migrating-to-v5.md, docs/framework/react/guides/migrating-to-react-query-4.md

A safe final pass should include dependency installation, codemod execution, formatting, linting, type checking, and behavioral tests. In v4 migrations, confirm devtools imports point at @tanstack/react-query-devtools and that the dependency is installed separately. In v5 migrations, search for old positional signatures that may remain in wrappers or variables. When reviewing diffs, prioritize query keys, filters, mutation keys, and query client calls because those are cache-identity and invalidation boundaries; an incorrect rewrite there can compile while changing application behavior.

Sources: docs/framework/react/guides/migrating-to-v5.md, docs/framework/react/guides/migrating-to-react-query-4.md

Next, read the migration guide for the version you are targeting, then run the smallest applicable transform on a committed branch. After the branch is green, continue with the related API pages for query keys, filters, QueryClient, and React hooks so that manual follow-up edits use the current TanStack Query vocabulary rather than the older call shapes.