DEV Community

Yuvraj Jindal
Yuvraj Jindal

Posted on

What the React 19 codemod doesn't tell you

The official React 19 migration codemod is useful. It handles the mechanical
stuff: ReactDOM.render → createRoot, string refs, prop-types cleanup.

But it leaves three categories of silent breakage that don't surface until
something breaks in production.

1. Peer-dep conflicts the installer swallows

When you bump react to 19 and run yarn install, you get a wall of
"incorrect peer dependency" warnings. Yarn proceeds anyway. npm either
blocks with ERESOLVE or silently overrides depending on your settings.

Either way, the real incompatibility is hidden. Your install succeeds.
Your CI is green. Your dependencies are broken.

2. element.ref time bombs

Radix UI 1.0.x reaches into element.ref internally. React 19 deprecated
this and added a compat shim — so it still works today. But the shim will
be removed in a future React minor, and when it is, every dialog, dropdown,
and popover in your app breaks at once.

The codemod doesn't touch this. Your tests don't catch it. It shows up
as a warning in stderr that's easy to miss:

3. tsc --noEmit false greens

If your root tsconfig.json uses project references (files: [] + references:
[...]), then tsc --noEmit checks zero files and reports zero errors.

The codemod runs tsc --noEmit to verify types. It passes. But your actual
type errors are still there — they only show up under tsc -b.

What I built

I ran into all three of these on a real migration and built keep-current
to catch them automatically.

It runs the full pipeline — codemods, dependency bump, install, tests,
type-check — then does a second-pass audit that surfaces what the codemod
marked as done but isn't.

Ran it against bulletproof-react (a well-known React architecture reference):

Category Green Amber Red
Dependencies 4 7 4
Type safety 1 0 0
Tests 1 0 0
Latent breakage 0 1 0

RED: @storybook/react, lucide-react, react-helmet-async need major
version bumps before React 19 is safe.

AMBER: All Radix UI packages work today but reach into deprecated
element.ref — they'll break on the next React minor.

GREEN: react-router, zustand, react-query-auth already support React 19.

The codemod said "done." It wasn't.

Try it

npx keep-current migrate --from 18 --to 19 ./your-repo
Enter fullscreen mode Exit fullscreen mode

Zero runtime dependencies. Runs locally. Open source.

https://github.com/YJ00793049/keep-current

Top comments (2)

Collapse
 
frank_signorini profile image
Frank

This is super helpful! I'm curious

Collapse
 
yj00793049 profile image
Yuvraj Jindal

Hey Frank — what are you curious about? Happy to go deeper on any of it.