Upgrading React Native is rarely difficult because of one dramatic change. It usually becomes risky because several small changes land at once: a React Native version update, a native dependency bump, an Xcode or Android Gradle plugin change, a package that no longer supports your setup, and a test suite that does not cover the right paths. This guide gives you a reusable, step-by-step checklist for how to upgrade React Native safely, whether you are moving one minor version, catching up after several releases, or upgrading inside an Expo-based workflow. The goal is simple: reduce upgrade risk, surface react native breaking changes early, and leave you with a repeatable process your team can revisit for every release.
Overview
If you want a dependable react native upgrade guide, the most important idea is this: treat upgrades as a controlled release process, not a package.json edit. A safe upgrade has three phases:
- Prepare: understand compatibility, freeze your baseline, and define what success looks like.
- Change: upgrade React Native and closely related tooling in a predictable order.
- Verify: test core app flows, native builds, performance, and release readiness before merging.
This approach works for small and large teams because it separates “making the code compile” from “proving the app is still healthy.” In practice, many failed upgrades happen because developers stop after the first successful local build.
Before making changes, decide which of these upgrade paths matches your app:
- Patch or small minor update: usually lower risk, but still worth testing on both platforms.
- Several versions behind: higher risk because multiple dependency assumptions may have drifted.
- Expo-managed or Expo-prebuild workflow: React Native changes are often tied to Expo SDK compatibility.
- Heavily native app: custom modules, unusual Gradle settings, Swift or Objective-C changes, and manual patches raise the risk.
If your app depends on many native modules, keep a compatibility reference nearby. A good starting point is the React Native Version Compatibility Matrix: React, Expo, Hermes, and Native Module Support. If you are still deciding how tightly you want a framework to manage the upgrade surface area, see React Native Framework vs No-Framework: Build Your First App with Expo, Navigation, and Native APIs.
Use this baseline checklist before every upgrade:
- Create a dedicated upgrade branch.
- Confirm the app builds and tests pass before changing anything.
- Document current versions of React Native, React, Expo if applicable, Hermes, Xcode, Android Gradle plugin, Gradle, Kotlin, CocoaPods, and key native libraries.
- Review release notes for React Native and any closely coupled packages.
- List business-critical app flows you must re-test manually.
- Plan a rollback path if the upgrade blocks release work.
That may feel procedural, but it saves time. When an issue appears later, you want to know whether it came from the React Native update itself, a toolchain shift, or an unrelated dependency cleanup that slipped into the same pull request.
Checklist by scenario
This section gives you a practical react native upgrade checklist by common scenario. Use the scenario that best matches your app, then merge in the general checks that follow.
Scenario 1: Small React Native version update
This is the best-case path: you are moving one version forward and your dependency graph is mostly current.
- Read the release notes first. Look for deprecations, renamed APIs, Metro changes, native template updates, and testing-related changes.
- Check React version alignment. React Native upgrades often expect a compatible React version. Do not upgrade one and assume the other will sort itself out.
- Upgrade only the minimum required packages. Avoid bundling unrelated package updates into the same branch.
- Regenerate or compare template changes. Even if you do not fully diff templates, inspect native files that commonly drift: Android build files, iOS Pod settings, app entry points, and Gradle wrappers.
- Reinstall dependencies cleanly. Remove node_modules, refresh lockfiles only if needed, and reinstall pods for iOS.
- Run the app on both platforms in debug and release-like modes. Debug success alone is not enough.
- Test navigation, forms, lists, authentication, deep links, push setup, and app startup. These are common break points because they touch several subsystems at once.
For many teams, this scenario becomes routine once the process is documented. The mistake is assuming “small” means “safe without verification.”
Scenario 2: Catch-up upgrade after skipping releases
If your app is several versions behind, resist the temptation to jump straight to the latest version without structure.
- Inventory everything native. Make a list of packages that touch camera, notifications, filesystem, authentication, gestures, maps, analytics, crash reporting, and custom native code.
- Identify hard blockers early. Some packages may no longer support your old configuration or may require a different setup on the target version.
- Consider stepping through major milestones. You do not always need to stop at every version, but large jumps are easier when validated in stages.
- Separate the upgrade into commits by concern. Example: one commit for core version changes, one for Android toolchain updates, one for iOS pod changes, one for app code fixes.
- Replace abandoned packages before or during the upgrade. Unsupported native modules create noise and can hide real React Native issues.
- Expect configuration drift. Metro config, Babel settings, TypeScript config, app permissions, and native build scripts often need cleanup.
- Expand your test pass. Include device-specific checks, background and foreground behavior, and at least one release build install per platform.
For older apps, this is also a good time to review technical debt honestly. If your project has accumulated one-off native patches, you may find that the upgrade is exposing maintenance issues rather than creating them.
Scenario 3: Expo-based upgrade
If you use Expo, the process is shaped by Expo SDK compatibility. That usually simplifies some decisions while making version alignment more important.
- Start with the target Expo SDK. Confirm which React Native version it maps to.
- Use Expo’s recommended upgrade path. Avoid manually forcing a React Native version that falls outside your Expo SDK expectations.
- Review config plugin and prebuild dependencies. Packages that modify native config may need updates at the same time.
- Check any custom native changes. If you use prebuild or have ejected areas, do not assume Expo insulates you from native drift.
- Re-test OTA-sensitive behavior carefully. Version boundaries can affect what kinds of updates are safe to ship and when a binary release is required.
- Verify development builds and production builds separately. A development build working does not guarantee parity with the app store build.
Expo can reduce upgrade friction, but only if you respect its version model. Treat Expo SDK upgrades as first-class release events, not routine chores.
Scenario 4: App with heavy native integrations
If your app uses camera modules, drawing tools, foldable layouts, custom device behavior, or other platform-specific features, your upgrade checklist needs one extra layer: hardware and capability testing.
- List all feature areas with native assumptions. Camera, sensor input, notifications, permissions, background tasks, Bluetooth, and media playback are common examples.
- Test permission prompts from a clean install. Permission timing issues often appear only on fresh installs.
- Verify layout behavior on unusual form factors. Foldables, tablets, and notched or cutout-heavy devices can expose regressions after rendering changes.
- Check gesture handling and animation performance. Native and JavaScript timing changes can alter touch responsiveness.
- Run on at least one older device or constrained emulator. Upgrade success on a fast flagship device can hide startup and memory regressions.
If your product leans heavily into device-specific experiences, related reads on reactnative.xyz can help you think beyond “does it compile?” For example, camera-heavy teams may care about Adaptive Camera UX in React Native: Building Around New Hardware Island Designs and Designing a Camera-First React Native App for Next-Gen Flagship Phones. Teams supporting broader device classes may also want Building Foldable-Ready React Native Layouts Before the Hardware Catches Up and Designing a Tablet-First React Native Experience for 11-Inch Android Devices.
What to double-check
Once the upgrade is in place, these are the areas most worth a second look. This is where many react native breaking changes show up indirectly.
1. Native build systems
- Android Gradle plugin and Gradle wrapper versions
- Kotlin version alignment
- CocoaPods installation and lockfile state
- Xcode build settings and signing behavior
- Any custom scripts in build phases or Gradle tasks
Build systems are easy to overlook because they may fail only in CI or only on a teammate’s machine.
2. Entry points and app registration
- Main application files
- Changes to app startup configuration
- Hermes and JavaScript engine assumptions
- Deep linking and navigation container setup
If the app launches inconsistently, start here before chasing component-level bugs.
3. Navigation and screen lifecycle
- Stack and tab navigation transitions
- Screen focus events
- Back button behavior on Android
- State persistence and deep links
Navigation bugs often appear after upgrades because they sit at the boundary between app state, rendering, and native containers.
4. Lists, gestures, and animations
- FlatList rendering and scroll performance
- Gesture responder conflicts
- Bottom sheets, modals, and portals
- Animation timing and frame drops
Even if you do not work on react native performance every day, upgrades are a good moment to capture basic before-and-after observations: startup feel, scroll smoothness, and memory behavior under normal use.
5. Permissions, notifications, and background behavior
- Camera, microphone, photo library, and location prompts
- Push notification registration
- Background refresh or task scheduling
- Cold-start behavior from notification taps
These areas deserve clean-install tests because existing simulator or device permissions can hide defects.
6. Release pipelines
- CI workflow changes
- Build cache behavior
- Artifact signing
- Android and iOS release build generation
If you maintain mobile release automation, do not stop at local success. A stable local build that fails in CI is still a blocked upgrade. This is especially important for teams managing react native ci cd or preparing to publish react native app updates on a schedule.
A practical verification pass might look like this:
- Run type checks and linting.
- Run unit tests and UI tests where available.
- Build Android debug and release.
- Build iOS debug and release or archive equivalent.
- Test core user journeys on physical devices.
- Check crash reporting, analytics initialization, and authentication.
- Validate one internal distribution build before merging.
Common mistakes
The easiest way to improve how to upgrade react native is to avoid the same class of mistakes every cycle. These are the ones that cost teams the most time.
Upgrading too many things at once
A React Native upgrade branch is not the place for a broad dependency refresh, design system rewrite, or navigation migration. Keep the surface area narrow so failures stay explainable.
Skipping release-note review
Even experienced teams lose time by troubleshooting changes that were clearly signposted in upgrade notes. Read first, then edit code.
Testing only on one platform
iOS and Android failures often differ in both cause and visibility. A safe upgrade requires both.
Trusting debug builds too much
Some issues appear only in release mode: minification, ProGuard or R8 behavior, Hermes differences, startup timing, or native initialization order.
Ignoring unsupported packages
Old packages can force you into brittle workarounds. If a library is no longer maintained, note that as part of the upgrade plan rather than patching around it silently.
Not documenting local fixes
If someone on the team had to clear caches, reinstall command line tools, or edit a native file by hand, write it down. Hidden setup steps turn into CI failures and onboarding confusion later.
Using upgrade work to postpone maintenance indefinitely
An app that stays too far behind becomes expensive to move. Regular smaller upgrades are usually easier to reason about than rare, urgent catch-up efforts. This is as much a release-management habit as a technical one.
There is also a team-level mistake worth naming: treating upgrade pain as random bad luck. In many codebases, upgrade pain follows patterns—unowned native modules, weak release checklists, or unclear compatibility rules. If this sounds familiar, it can help to examine platform work as a long-term maintenance practice rather than a series of isolated emergencies. A broader perspective on platform turnarounds and technical debt appears in What a CEO Return Can Teach Mobile Teams About Platform Turnarounds and Technical Debt.
When to revisit
This checklist is most useful when treated as a living release tool. Revisit it whenever the underlying inputs change, not just when you are forced into a major migration.
Use it again in these situations:
- Before seasonal planning cycles, when you are deciding whether to schedule framework maintenance.
- When workflows or tools change, such as new CI providers, build machines, or team conventions.
- When you add a new native dependency, especially one tied to camera, notifications, authentication, maps, or media.
- When Apple or Android tooling changes, because build chain shifts can affect the next React Native update.
- When your app starts targeting new device classes, such as tablets, foldables, or hardware-specific UX patterns.
- When you notice upgrade drift, meaning the team has delayed framework work for long enough that version gaps are growing.
To make this practical, end each upgrade with a short post-upgrade note:
- Record the versions you moved from and to.
- List the packages that required special handling.
- Capture build or CI fixes that were necessary.
- Note the manual test flows that found real regressions.
- Add one improvement to your next react native upgrade checklist.
If you do that consistently, each release gets easier. The checklist stops being generic advice and becomes part of your team’s operating system.
A good final action plan for your next upgrade is simple:
- Create an upgrade branch.
- Freeze the baseline with passing builds and tests.
- Review compatibility and release notes.
- Upgrade in a narrow, documented scope.
- Verify both platforms in debug and release-like conditions.
- Test business-critical flows manually.
- Merge only after CI and internal distribution builds are healthy.
That process is not flashy, but it is reliable. And reliability is what makes a React Native version update sustainable over time.