Upgrading a React Native app is rarely about a single package. It is a coordination problem across React Native, React, Expo, Hermes, native build tools, and the libraries that bind into iOS and Android. This compatibility hub is designed to help you reason about those moving parts before you upgrade, not after your build breaks. Use it as a practical reference for planning version changes, auditing dependencies, and deciding whether your app should stay on its current stack, move incrementally, or prepare for a wider migration.
Overview
A useful React Native compatibility matrix is less about memorizing version numbers and more about understanding relationships. When teams talk about react native upgrade compatibility, they are usually dealing with one or more of these questions:
- Which React version matches the React Native version in the app?
- If the project uses Expo, which Expo SDK lines up with that React Native release?
- Is Hermes enabled, optional, or effectively assumed by the surrounding tooling?
- Will common native modules still compile after the upgrade?
- Do navigation, gesture, animation, testing, and build tools need to move at the same time?
Those questions matter because React Native is not a single runtime in isolation. A modern app often includes:
- The JavaScript layer: React, React Native, TypeScript, Metro, Babel, ESLint, and test tooling
- The runtime layer: Hermes or another JavaScript engine
- The app framework layer: Expo managed workflow, Expo prebuild, or a bare React Native setup
- The native integration layer: Gradle, Android SDK, Xcode, CocoaPods, and native module bridges
- The library layer: navigation, storage, forms, camera, auth, analytics, notifications, and UI packages
That is why a compatibility matrix is useful as a hub rather than a static table. The exact version mapping changes over time, but the decision process stays relevant. If you approach upgrades by dependency relationship instead of guesswork, you can reduce failed builds, runtime regressions, and last-minute rollback work.
For teams deciding whether to build with a framework-first approach or a more manual native setup, it helps to review React Native Framework vs No-Framework: Build Your First App with Expo, Navigation, and Native APIs. That framing often determines how strict your compatibility requirements will be.
What this hub covers
This article focuses on the compatibility logic behind these common upgrade paths:
- React Native and React: the foundational pairing that must align before anything else
- Expo and React Native: framework-level coupling that strongly shapes which versions are realistic
- Hermes and React Native: runtime support, debugging behavior, and performance implications
- Native modules and platform tooling: build compatibility across Android and iOS
- Common library groups: navigation, animation, gesture handling, camera, auth, notifications, testing, and forms
It does not try to claim a permanent list of exact supported versions. That kind of list becomes stale quickly. Instead, it gives you a durable way to verify support using official package metadata, release notes, lockfiles, and build pipelines.
Topic map
If you need a repeatable way to evaluate react native expo compatibility or a broader react native compatibility matrix, start with the stack from the center outward. The order matters.
1. Core alignment: React Native, React, and JavaScript tooling
Your first checkpoint is the core app runtime. React Native depends on a compatible React version, and both influence how Metro, Babel presets, and TypeScript behave in practice. Before changing anything else, confirm:
- The installed React version matches the expectation of the target React Native release
- Your TypeScript version is supported by the template, config, and library ecosystem you use
- Metro and Babel config changes are accounted for, especially if your project has custom aliases, transformers, or monorepo integration
- Your test runner setup still understands the package transforms required by the upgraded dependencies
A simple rule helps here: upgrade the core platform first on paper, not in code. Write down the intended target versions before editing package.json. That alone prevents many half-upgraded states.
2. Expo compatibility: framework constraints first
If you are working in Expo, the framework becomes the strongest compatibility gate. In most Expo projects, you do not freely choose any React Native version you want. Instead, the Expo SDK sets a supported baseline for React Native, React, and a collection of Expo modules.
When checking expo sdk react native version compatibility, review the project through these questions:
- Is the app on the managed workflow, prebuild, or a more customized native setup?
- Are you using Expo Router, EAS Build, expo-updates, expo-notifications, expo-camera, or other modules that should be upgraded together?
- Have you pinned package versions manually that the Expo ecosystem normally manages for you?
- Are custom native changes minimal enough that an Expo SDK upgrade stays straightforward?
In framework-led projects, resist the urge to upgrade React Native independently first. The more reliable path is usually to choose the desired Expo SDK and let that choice drive the React Native and React pairing.
3. Hermes compatibility: runtime and debugging expectations
The question of react native hermes version is usually less about hand-picking Hermes and more about confirming the runtime assumptions of your chosen React Native release. Hermes affects startup behavior, memory characteristics, stack traces, source maps, and some debugging workflows.
When reviewing Hermes support, check:
- Whether Hermes is enabled by default in your target setup
- Whether your debugging tools and source map handling are configured for the runtime you use
- Whether any third-party packages depend on runtime-specific behavior
- Whether release builds behave differently from debug builds after the change
Hermes also intersects with performance work. If your app already struggles with startup time or bridge-heavy interactions, version changes can expose bottlenecks that were already present. This is a good point to revisit your profiling habits, not just your package versions.
4. Native module support: where upgrades usually become real
Most upgrade pain shows up when native modules enter the conversation. Pure JavaScript packages often fail loudly and early. Native modules can fail later, during CocoaPods install, Android compilation, device-only runtime paths, or release signing.
Audit native module support by grouping packages into risk levels:
- Low risk: JavaScript-only utilities with minimal React Native coupling
- Medium risk: common ecosystem packages such as forms, validation, storage wrappers, and theming helpers
- High risk: camera, notifications, authentication, background tasks, maps, in-app purchases, media, gesture systems, and advanced animation packages
For each native dependency, verify:
- Its declared peer dependencies
- Its release notes or migration guides
- Whether it supports the New Architecture if your app is moving in that direction
- Whether iOS and Android support are equally mature
- Whether the package still has active maintenance
This matters even more for hardware-sensitive features. If your app touches camera behavior, advanced sensors, or new device form factors, compatibility is not only about compilation. It is also about behavior on specific classes of devices. For that broader lens, articles such as Adaptive Camera UX in React Native: Building Around New Hardware Island Designs and Building Foldable-Ready React Native Layouts Before the Hardware Catches Up are useful companions.
5. Library group compatibility: upgrade by ecosystem cluster
Many teams upgrade one package at a time, but React Native libraries often move in clusters. Common clusters include:
- Navigation cluster: React Navigation, safe area handling, screens, gestures, deep linking, Expo Router
- Animation cluster: Reanimated, gesture handler, bottom sheets, shared transitions
- Media cluster: camera, image pickers, video, file system access
- Auth and network cluster: secure storage, web auth, refresh tokens, API clients
- Testing cluster: Jest, React Native Testing Library, Babel config, mocks, end-to-end tooling
Thinking in clusters helps you avoid a common trap: a core package upgrade succeeds, but one adjacent library still assumes an older API shape. The result is not always a compile error. Sometimes it is a broken gesture, a missing screen transition, or an authentication callback that silently fails.
Related subtopics
A compatibility hub becomes more useful when it points to the surrounding decisions that shape version support in real projects. The subtopics below are where most upgrade investigations eventually lead.
Expo managed workflow vs bare workflow
Compatibility decisions look very different depending on how much native code you own. In a managed Expo app, the upgrade path is narrower but often more predictable. In a bare app, you have more flexibility, but you also inherit more responsibility for Gradle, Xcode, pods, signing, native patches, and module-level fixes.
If your team is unsure which side of that tradeoff fits your app, start with architecture rather than package churn. A framework choice made early can simplify years of upgrades later.
New Architecture readiness
Some projects are not just upgrading versions; they are moving toward the New Architecture. That raises a separate compatibility question: does each native dependency support the architecture features your target release expects? Even when support exists, you may need to validate custom modules, codegen behavior, and package-specific caveats.
Treat this as its own migration stream. Do not hide it inside a routine dependency update.
Performance and regression testing
Version compatibility is not only about whether the app builds. It is also about whether it still performs well. After an upgrade, compare:
- Cold start time
- Navigation smoothness
- List rendering behavior
- Memory use on lower-end devices
- Animation consistency
- Bundle size and app size where relevant
A successful upgrade that quietly worsens startup or scroll performance is still a compatibility problem. The code compiles, but the experience regresses.
Device-specific native feature support
Apps using cameras, stylus input, foldables, high refresh displays, or unusual screen layouts should consider hardware compatibility as part of the matrix. A module may technically support your React Native version while still requiring UX or native handling adjustments for newer devices. Related reads include How to Build Pressure- and Tilt-Aware Drawing Tools in React Native, How to Build Battery-Aware, High-Refresh Mobile Experiences for Budget 5G Devices, and Designing a Tablet-First React Native Experience for 11-Inch Android Devices.
Technical debt and timing
Sometimes the real compatibility issue is not the next version jump. It is the accumulated distance from the ecosystem. The longer a project waits, the more likely it is to hit compounded breaking changes across the toolchain. That is as much a maintenance discipline issue as a dependency issue. For a strategic angle on that pattern, see What a CEO Return Can Teach Mobile Teams About Platform Turnarounds and Technical Debt.
How to use this hub
If you want this article to function like a working upgrade checklist rather than a one-time read, use the process below every time you touch your stack.
Step 1: Inventory the current app state
Create a snapshot of the current environment before planning an upgrade. Capture:
- React Native version
- React version
- Expo SDK version if applicable
- Hermes enabled or disabled state
- Top native modules and their versions
- Android Gradle and compile settings
- Xcode and CocoaPods assumptions
- CI build image assumptions
This should live in a document your team can revisit, not in one engineer's memory.
Step 2: Define the target upgrade boundary
Be specific about what kind of change you are making:
- Patch or minor package refresh
- React Native minor upgrade
- Expo SDK upgrade
- Runtime change involving Hermes behavior
- New Architecture evaluation
- Native module replacement or removal
A clear boundary prevents a “while we are here” expansion that turns a manageable upgrade into an uncontrolled migration.
Step 3: Build a temporary compatibility matrix for your app
Your project-specific matrix can be simple. A table or markdown list is enough. Track columns such as:
- Package or tool
- Current version
- Target version
- Dependency relationship
- Native impact
- Migration notes
- Test status
- Owner
The important part is not format. It is visibility.
Step 4: Upgrade in the right order
A practical sequence is often:
- Choose the target framework baseline: Expo SDK or plain React Native release
- Align React and core tooling
- Confirm Hermes expectations
- Update high-risk native modules one cluster at a time
- Run platform builds separately for Android and iOS
- Validate navigation, auth, notifications, camera, and release builds
Do not judge success from a simulator home screen alone. Test the flows that rely on native code, permissions, deep links, background behavior, and production-like build settings.
Step 5: Keep a rollback path
Even disciplined upgrades can surface hidden issues. Tag a known-good state, keep lockfiles intact, and avoid mixing broad refactors into the same branch. Compatibility work is easier to reverse when it is isolated.
Step 6: Turn the result into team knowledge
Once the upgrade is complete, keep the matrix. Note what failed, what required native intervention, and what should be checked next time. Over time, that internal record becomes more valuable than any generic online version table because it reflects your actual app.
When to revisit
Come back to this compatibility hub whenever one of these triggers appears:
- You are planning a React Native or Expo upgrade
- You are adopting a new native module such as camera, notifications, maps, or auth
- You are enabling Hermes, changing debug tooling, or evaluating runtime performance
- You are preparing for a New Architecture migration
- You are updating CI images, Xcode, CocoaPods, Android Gradle, or release pipelines
- You notice that one platform has started drifting from the other in behavior or build reliability
- You are onboarding a new device class, hardware feature, or screen form factor
A good habit is to review compatibility before roadmap planning, not during a release emergency. Put a lightweight dependency audit into your quarterly engineering maintenance cycle. For each audit, answer four questions:
- What is our current core stack?
- Which dependencies are most coupled to native tooling?
- Which upgrade path would be smallest and safest right now?
- What should we test first if we move?
If you maintain this as a living process, compatibility becomes less of a fire drill and more of a predictable part of React Native app development. That is the real value of a version matrix: not a frozen chart, but a repeatable way to make better upgrade decisions.
As the ecosystem expands into more hardware-aware and native-heavy use cases, this topic only becomes more important. If your roadmap includes advanced camera work, wearable integration, AR-adjacent features, or unconventional displays, version support and native module maturity deserve earlier attention, not later. For a broader look at where those demands are heading, see Why the Next Wave of Mobile Apps Will Need AI, AR, and Wearable Integration by Default.
Your next action is simple: document your current stack, identify your highest-risk native dependencies, and build a small compatibility matrix for your own app before the next upgrade cycle starts.