BEON.tech
BRAND & COMPANY

How to Upgrade React Native from 0.70 to 0.81 in Two Weeks

Julio Mussi
Julio Mussi

A React Native upgrade is one of those tasks that looks straightforward on paper and turns into a multi-week ordeal in practice. This is the story of how to took a production app from React Native 0.70.15 to 0.81.6 in about two focused weeks. Incrementally, with stable branches ready for QA along the way.

For the last six years, across different products and teams, I kept hearing the same sentence:

“We need to upgrade React Native.”

Different company, same story. A giant AppDelegate. Obscure SDKs with little documentation. Old native patches nobody wants to touch. Too many dependencies. And somehow the deadline is always next Friday.

If you’ve worked with React Native long enough, you know how this usually goes. The problem is rarely the execution: coffee ready, Stack Overflow in one tab, React Native Upgrade Helper in another, editor in the middle. Build fails. Try again. Ask two teammates for help. Delete the branch. Start over.

A few days later: “The upgrade is done.” Which often means: it compiles.

Then come the real problems. Build issues. Runtime crashes. A red box covering the screen. Animations behaving differently on iOS. Android suddenly slower. A strange Safari regression on web.

We search to the ends of Google, hoping someone somewhere upgraded to the same version and used the same packages. If not, we write an issue on GitHub and wait three or four weeks for help. And then, we fix it.

QA opens a pile of tickets. We fix them. Release moves again, but we can finally have some closure.

Then, right before launch: “The new Xcode version is mandatory now.”

The good? A new RN upgrade. The bad? A new RN upgrade. This post is my attempt to save some time and sanity for the next team facing that situation.

The Upgrade Path from React Native 0.70 to 0.81

We did not jump from 0.70 straight to 0.81. The main challenge was the number of native modules, custom iOS code, and SDKs the app has. Without this workflow, we would have had to create a new project and migrate to it.

We walked there instead:

0.70.15 → 0.72.17 → 0.76.9 → 0.78.3 → 0.81.6

Each step had its own branch, validation gate, and rollback point. During this React Native upgrade, we also ran automated tests while working through each step.

Tools and Setup for the React Native Upgrade

The biggest difference this time was how the work was organized. Most upgrade efforts are one engineer handling everything sequentially: compare diffs, fix config files, debug builds, test flows, research package issues, repeat. That works, but it’s slow and mentally expensive.

For this upgrade, we used:

  • Cursor — for AI-assisted code editing
  • Playwright MCP — very specific to our use case: a hybrid React Native/Web app
  • rn-upgrade-helper-MCP — the oil in this engine
  • Opus — parallel agent workflows for planning, validation, execution, and testing

How to Plan a Large React Native Upgrade

For each upgrade step, we kept a living document. For example: docs/plans/rn-081-upgrade-master-plan.md

That document became the source of truth for the upgrade. It included:

  • Canonical React Native diff sources
  • The exact version delta
  • Known blockers
  • Dependency decisions
  • Patch reconciliation
  • Rollback gates
  • Deferred items
  • Final validation results

This helped a lot with keeping tabs on what was going on, instead of just trusting AI to not miss anything. Whenever we progressed, we documented it. The plan also included instructions for the agents: all the details, asks, and expectations.

How to Set Up Agents for a React Native Upgrade Guide

Planner Agent

The Planner read the React Native template diff and produced a file-by-file migration checklist. It used the React Native Upgrade Helper, rn-diff-purge, the React Native upgrader MCP, the current app files, and previous upgrade plans.

It was never supposed to touch the code. It was kind of a to-do list:

  • What changed in the RN template
  • Whether it applied to our app
  • What files needed edits
  • What could be skipped because our app intentionally differs from the template

This was especially important because our app has custom native code, a hybrid Swift and ObjC++ AppDelegate setup, many native modules, and old architecture constraints.

Verifier Agent

The goal here was to ensure nothing was overlooked. The Verifier checked:

  • React Native Upgrade Helper against the MCP diff
  • Package compatibility against the target RN version
  • React compatibility
  • Old Architecture versus React Native New Architecture requirements
  • Native SDK risks
  • Active patches
  • Deferred items from previous upgrade steps

It was also invaluable for saving tokens. Iterating again at the end would have been expensive.

Executor Agent

This one just ran the plan.

Tester Agent

The Tester ran verification gates throughout the upgrade. Depending on the phase, that meant:

  • Web lint
  • Web unit tests
  • Web production build
  • iOS build
  • Simulator smoke checks
  • Targeted runtime validation
  • Browser automation for the web surface

Web checks were the fast feedback loop: cheaper to run, and if something was really broken, the app usually would not compile or the test suite would fail quickly. iOS smoke tests and builds were saved for milestone gates or native-risk changes.

Strategy: Clean the House Before Touching React Native Core

This was probably the most important call in the whole project.

Phase 1 — Replace Abandoned Libraries First

Still on RN 0.70, we first removed packages that would almost certainly become blockers later. We migrated packages that did not support the React Native New Architecture, were stale, or had been migrated to a different org or namespace.

Decision buckets:

  • Dead packages: remove
  • Abandoned packages with maintained forks: replace before touching RN core
  • Official renames: migrate when the target RN version supports them
  • Behavioral major upgrades: do one at a time with smoke checks
  • New Architecture-only upgrades: defer
  • Web/tooling migrations: split into separate work unless they block the upgrade
  • Small compatibility issues: patch temporarily, with an exit condition

Concrete replacements:

FromTo
@react-native-community/clipboard@react-native-clipboard/clipboard
react-native-fast-image@d11/react-native-fast-image
react-native-image-resizer@bam.tech/react-native-image-resizer
rn-fetch-blobreact-native-blob-util
react-native-fs@dr.pogodin/react-native-fs

This separates dependency debt from core RN upgrade issues. When something breaks later, you know where to look.

The Patch First Approach

During the upgrade React Native process, patches helped keep the main path moving. Keeping Old Architecture meant we could not simply upgrade every native library to its newest major version, some latest versions assumed TurboModules, Fabric, or bridgeless behavior.

In those cases, a small compatibility patch was safer than dragging a React Native New Architecture migration into the same branch.

The rule was simple: patches had to be small, time-boxed, and documented with a removal condition. If the patch started spreading across too many files or touching architecture internals, it was not a patch anymore. It was a migration and we treated it as one.

That is how we handled cases like:

  • react-native-mmkv v2 staying on Old Architecture with a compatibility patch
  • @dr.pogodin/react-native-fs needing Old Architecture fallback behavior
  • react-dom needing a compatibility shim while the web app still used CRA
  • @react-navigation/native needing React 19 compatibility before a full v7 migration

By the end of the React Native 0.81 branch, there were still seven active patches. All known, documented, validated, and attached to future removal paths.

Phase 2 — Upgrade in Steps

Instead of one giant jump, every step in this React Native upgrade guide had:

  • Its own plan file
  • Successful build
  • Test pass
  • Smoke validation
  • Rollback point

Phase 3 — Stay on Old Architecture on Purpose

We kept RCT_NEW_ARCH_ENABLED=0. The React Native New Architecture is valuable, but it also changes rendering, native modules, and runtime behavior. Doing that together with React 18 → 19, multiple RN upgrades, library replacements, and compiler/toolchain updates would have increased the risk dramatically.

We have almost 40 custom native modules written in the old architecture. We also have SDKs that do not support the React Native New Architecture. Migrating without a major rewrite would have been impossible.

The decision was to migrate to the last version where New Architecture is optional.

Real Problems We Hit During the React Native 0.81 Upgrade

Realm

realm@12.14.2 is deprecated and was a risk item. We treated it as a hard validation gate during the React Native 0.81 move. If Realm broke on iOS, we would stop and replan.

Skia + React 19

@shopify/react-native-skia@1.x had compatibility issues with React 19 internals. Skia v2 would require New Architecture, which we intentionally postponed. We added runtime guards around template generation paths. The app remains stable, and unsupported paths fail gracefully instead of crashing, another win from the patch first approach.

MMKV

react-native-mmkv@2.x is tied to Old Architecture. v3 would require a broader architecture move, so we kept v2 with a small compatibility patch and documented removal criteria.

Results: What This React Native Upgrade Delivered

The obvious win was reaching React Native 0.81.6. Along the way:

  • Dead dependencies were removed
  • Abandoned packages were replaced with maintained forks
  • Deferred items from earlier upgrades were resolved when the target RN version unlocked them
  • React 19 cleanup was handled incrementally
  • The React Native New Architecture decision was separated from the RN version jump
  • Risky systems like Realm, Skia, MMKV, Navigation, Sentry, and RNFS were tracked directly
  • Every patch had a reason and a removal path

And we had some numbers to show for it:

  • 228 web test suites passing
  • 7 active patches documented with a reason and exit path
  • Production dependencies reduced from 124 to 68

Final Takeaway

Large React Native upgrades often feel chaotic because they mix too many problems at once: outdated libraries, native changes, and product pressure all at the same time.

Breaking the work into smaller decisions changed everything. What usually drags for months became a focused sprint.

If you’re staring at an old RN version right now, the advice is simple:

  • Clean the house first
  • Move in steps
  • Automate the repetitive parts
  • Validate constantly
  • Keep scope under control

The React Native Upgrade Helper is your starting point for understanding the diff between versions. Pair it with a solid plan document and the process becomes manageable, even across a 11-version jump.

FAQs

How long does a React Native upgrade from 0.70 to 0.81 really take?

About two weeks of focused execution, with prior knowledge of the codebase and strong automation support. Without the incremental strategy and agent workflow described here, the same work could take months.

Should I enable the React Native New Architecture during the upgrade?

No/not at the same time. Architecture migration deserves its own scope. Mixing it with a large version jump increases risk significantly. Migrate to the last version where New Architecture is optional first, then tackle the architecture separately.

Was this upgrade only possible because of AI tools?

No. Good engineering process mattered more than the tools. The agents mainly accelerated repetitive work and validation. The plan, not the AI, made the work safe.

Is it better to jump directly from 0.70 to 0.81 or go step by step?

Step by step, always. Incremental steps make regressions easier to isolate and reduce overall risk. Each intermediate version should have its own branch, build validation, and smoke tests before moving forward.

How do you decide whether to patch or upgrade a library during a React Native upgrade?

If the fix is small, local, and easy to remove later, patch first. If the patch starts touching too many files, native internals, or architecture behavior, it is not a patch anymore. It is a migration. Treat it accordingly.

What should a team do before starting a React Native upgrade?

Audit the dependencies first. Find abandoned packages, active patches, native SDKs, Old Architecture constraints, and packages that only work on newer RN versions. Use the React Native Upgrade Helper to understand the template diff before writing a single line of code.

Ready to build your team in Latin America?

Let us connect you with pre-vetted senior developers who are ready to make an impact.

Get started
Julio Mussi
Written by Julio Mussi