Upgrades · Playbook

How to upgrade React Native in 2026: a playbook that actually works

Published April 1, 2026 · 12 minute read
TL;DR

A React Native upgrade is four jobs. Audit. Plan. Execute. Verify.

Most failures aren't failures of execution. They're failures of audit and planning — someone skipped to the commands before they knew what they were upgrading.

Do it in version-jump-sized branches. Staircase, don't leap. Verify on physical devices, not just CI.

Most React Native upgrade guides tell you to open the upgrade helper, diff the config, and run npm install. That works for apps that are one version behind and use a tutorial-level set of dependencies.

It doesn't work for real codebases.

Real codebases are 3–18 months behind. They have custom native modules. They pull in libraries whose maintainers haven't touched them in a year. The lockfile has 1,200 entries. The Xcode project has twelve targets nobody remembers configuring.

This is a playbook for those upgrades. The ones that actually break.

On this page
  1. An upgrade is four jobs, not one
  2. Phase 1 — Audit
  3. Phase 2 — Plan
  4. Phase 3 — Execute
  5. Phase 4 — Verify
  6. Common failure modes
  7. When to DIY, when not to
  8. Upgrade tooling, quick reference
  9. FAQ

An upgrade is four jobs, not one

The most common mistake is treating an upgrade as a single task. "Upgrade React Native" goes on a sprint board, a senior engineer picks it up, and two weeks later they're in a branch with 300 files changed and no clear path back.

The shape of the work is actually four phases:

  1. Audit. What's in the codebase? What are we upgrading?
  2. Plan. In what order do we do this? What's the staircase?
  3. Execute. What breaks, and how do we fix it in sequence?
  4. Verify. How do we know it didn't silently regress?

Most upgrades that fail, fail in phase 1 or phase 2. Execution gets all the attention because it's the part with commits. But if you skip the first two phases, execution is just you discovering the unknowns live.

Phase 01

Audit

Before touching a line of code, inventory everything the upgrade will touch. This isn't optional. This is where the surprises live.

Direct dependencies

Run npm ls --depth=0 or yarn list --depth 0. For each direct dependency, answer:

Transitive dependencies

Your lockfile is the actual universe. package.json lists the ones you opted into. The lockfile lists the 1,200 you didn't. Run npm audit. Count critical and high. That's your CVE surface.

Native modules

Open ios/Podfile and android/build.gradle. Anything pinned to a specific version. Anything with a custom build phase. Anything that references a legacy Android API level. Any CocoaPods pinned to source repos instead of registry. All of it matters.

Build configuration

Xcode project file, Gradle config, Metro config, Babel config, TypeScript config. Each one has defaults that React Native expects. Each one probably has customizations your team added that aren't in the template.

CI

What runs on every PR? What breaks when node version changes? Which caches will go stale? Does your CI runner have the right Xcode version for your target RN?

Output of Phase 1: a single spreadsheet with one row per thing the upgrade touches. Columns for current version, target version, compat notes, known issues, effort estimate. You'll reference this document every day for the next three weeks.

Phase 02

Plan

You don't go from 0.68 to 0.76 in one jump. You staircase.

The version path

Minor-by-minor. Sometimes patch-by-patch if a release introduced a known regression. For each hop, identify:

The hard decisions, up front

Decide these before you start writing code. Not during.

The order of operations

Infrastructure first — React Native, Expo SDK, Hermes. Then foundation libraries — react-native-screens, react-native-gesture-handler, react-native-reanimated. Then feature libraries — navigation, Firebase, storage, network. App code last.

Upgrading leaf dependencies before the infrastructure underneath them is a reliable way to get stuck. The leaves will reject your work.

Phase 03

Execute

One branch per version jump. Not one branch for the whole upgrade.

The discipline

The libraries that break most

If you're going to spend extra time on any library, it's these:

Verify native builds after every step

npm install passing doesn't mean it builds. tsc passing doesn't mean it builds. The only thing that tells you the native build works is a successful xcodebuild and gradle assembleDebug.

Run both after every non-trivial bump. If either fails, stop. Fix it before moving on. Don't accumulate failures and try to untangle them at the end.

Phase 04

Verify

Tests passing doesn't mean it works. This is where most teams stop and ship anyway.

Core flow verification, on physical devices

Simulator-only verification is a trap. Simulators skip whole classes of bugs — audio, camera, biometrics, background modes, anything that talks to real hardware. Exercise the core flows on at least one iPhone and one Android device.

Core flows means: cold start, login, the three features that 80% of your users use, log out, background, resume, deep link entry.

Performance regressions

Capture these before you start:

Compare after the upgrade. If any of these got meaningfully worse, that's a signal, not a shrug.

TestFlight and Internal Track before production

Always. Even if you're confident. Ship the upgraded build to a beta channel for at least a week before promoting. The bugs you didn't find in QA will surface in TestFlight.

The upgrade is done when

Build passes on both platforms with no warnings you can't explain. Core flows pass on physical devices. Cold start time, bundle size, and crash-free rate are within tolerance of the pre-upgrade baseline. Anything less is "we ran out of time," not "done."

Common failure modes

The mistakes that eat upgrades, in rough order of frequency:

When to DIY, when not to

DIY if:

Don't DIY if:

A multi-version upgrade on a real codebase typically runs 80–160 hours of senior engineer time. At $150–$250 per hour, that's $12,000–$40,000 in opportunity cost — plus the roadmap delay. Compare that to whatever outside option you're considering before deciding.

Upgrade tooling, quick reference

ToolWhat it doesWhen to use
react-native upgrade-helperWeb diff of template config between two RN versionsStarting point for every version hop
npx @react-native-community/cli upgradeCLI equivalent of the upgrade helperWhen you want a patch applied automatically
npm-check-updatesLists available dependency updatesPhase 1 audit; use with --target minor or --target patch
npm audit / yarn auditReports known CVEs in the lockfileEvery phase. Especially before you ship
RN New Architecture compat matrixLists which popular libraries support Fabric and TurboModulesPhase 2 planning
Expo SDK release notesMaps Expo SDK versions to supported RN versionsPhase 2, if you use Expo
depcheckFinds unused dependenciesPhase 1. Fewer deps is fewer upgrade surface
Our free scannerCVE + outdated package check for React Native lockfilesPhase 1 audit. 90 seconds, no signup

Not sure where you stand?

Run the free scanner against your lockfile. You'll get a ranked list of known CVEs and outdated packages in about 90 seconds — a useful input to Phase 1 of your own audit.

Frequently Asked Questions

How long does a React Native upgrade take?

For a single-version hop on a healthy codebase, one to three days. For a multi-version upgrade on a codebase six to eighteen months behind, 80 to 160 hours of senior engineer time is typical. The variance is driven by native module count, custom build configuration, and how aggressively the codebase used bleeding-edge libraries.

Can we skip React Native versions?

Technically yes. Practically, don't. Each version jump introduces its own breaking changes, and debugging a failure when you've skipped three intermediate versions is much harder than doing it incrementally. Upgrade one minor version at a time, verify, then move to the next.

What's the difference between upgrading React Native and upgrading dependencies?

They're coupled but distinct. React Native's version sets a ceiling on what many of your native-adjacent dependencies can do. But a lot of your upgrade work is in the packages on top of React Native — gesture handler, reanimated, screens, Firebase, storage, navigation. You'll often do more work updating those than on the React Native version itself.

What order should we upgrade dependencies in?

Infrastructure first — React Native, Expo SDK if used, Hermes. Then foundational libraries that everything else depends on — react-native-screens, react-native-gesture-handler. Then feature libraries — navigation, Firebase, storage, network. App code last. Trying to upgrade leaf dependencies before the infrastructure underneath them is a reliable way to get stuck.

How do we know when the upgrade is done?

Build passes on both platforms with no warnings you can't explain. Core user flows pass on physical devices, not just simulators. Cold start time and bundle size are within tolerance of the pre-upgrade baseline. Crash-free rate in TestFlight or Internal Track matches production. If any of these are worse, you're not done — you're at the part where people usually stop and ship anyway.