DEV Community

Cover image for A dependency-first checklist for upgrading React Native
Rushikesh Pandit
Rushikesh Pandit

Posted on

A dependency-first checklist for upgrading React Native

Most upgrade guides start with the template diff. I now start about five steps earlier, because that's
where the surprises live.

1. List your native dependencies

A native dependency is any package with an ios/ folder, an android/ folder or a .podspec. Each one
is a separate compatibility question. Here's a small script (Node 18+, run from your project root):

// list-native-deps.mjs
import { readdirSync, existsSync, statSync } from 'node:fs';
import { join } from 'node:path';

const root = join(process.cwd(), 'node_modules');
const isNative = (dir) =>
  existsSync(join(dir, 'android')) ||
  existsSync(join(dir, 'ios')) ||
  readdirSync(dir).some((f) => f.endsWith('.podspec'));

const candidates = [];
for (const name of readdirSync(root)) {
  if (name.startsWith('.')) continue;
  if (name.startsWith('@')) {
    for (const sub of readdirSync(join(root, name))) candidates.push(join(root, name, sub));
  } else {
    candidates.push(join(root, name));
  }
}

for (const dir of candidates) {
  try {
    if (statSync(dir).isDirectory() && isNative(dir)) console.log(dir.replace(root + '/', ''));
  } catch {}
}
Enter fullscreen mode Exit fullscreen mode

Caveat: with pnpm, only your direct dependencies appear at the top level of node_modules, so you'll see
direct native deps but not every transitive one.

2. Check each against the target version

For each native dependency: when was the last release? Does the README or changelog mention your target
React Native version? Are there open issues with the version number in the title? Write the answer down
as compatible / unknown / broken.

3. Check peer dependency ranges

Look at peerDependencies for react and react-native in each library. A pinned upper bound is an early
warning, even if everything installs with --legacy-peer-deps.

4. Verify the toolchain

Read the release notes for your target version and list the required Xcode, JDK, Node and Android Gradle
Plugin versions. Compare with your CI images and your teammates' machines. Mismatches here fail late.

5. Dry-run on a throwaway branch

Bump, install, build both platforms, run the app. Time-box it. Record every failure with the file and the
error. This list is your real estimate.

6. Now apply the Upgrade Helper diff

With the risk list in hand, the diff is much easier to apply, because you know what's likely to collide.

One hop or several?

Jumping many versions at once is faster when it works and harder to debug when it doesn't. If your dry run
shows many unknowns, stepping through intermediate versions can isolate failures. Decide using your risk
list, not habit.

Automating steps 1–4

I'm building rn-upgrade-doctor to automate the inventory and compatibility checks and produce a
project-specific risk report. CLI public on 20 Oct: rn-upgrade-doctor

What step would you add to this list?

Top comments (1)

Collapse
 
lassiecoder profile image
lassiecoder •

Step 5 is where most of the time goes, so one addition to it: for each failure, record the first
error, not the last line. Gradle and Xcode both end with a generic BUILD FAILED, and the line that tells you which column to put the library in (a checkDebugAarMetadata compileSdk mismatch, a dependency that won't resolve, a Kotlin error inside node_modules//android) is usually far above it.

For step 4, I'd add ./gradlew -version next to the release notes. It shows the JDK the Gradle
daemon actually runs on, which isn't always the one java -version prints, especially between
Android Studio and CI.

Disclosure: I built an open-source CLI for exactly that part of step 5.
(cd android && ./gradlew assembleRelease) 2>&1 | npx rn-build-doctor analyze - finds the first real error and quotes the log lines it's based on, offline: github.com/lassiecoder/rn-build-do...