React Native upgrades are notorious for breaking apps. Here's how I approach them without losing my sanity.
Before You Start
- Commit everything - Clean git state
- Create a branch -
git checkout -b upgrade-rn-0.73 - Read the changelog - Actually read it
- Check your dependencies - Some might not support the new version
Step 1: Use the Upgrade Helper
Go to react-native-community.github.io/upgrade-helper
Select your current version and target version. It shows exactly what changed.
Step 2: Upgrade Approach
For Expo (Managed)
The easy path:
# Check current SDK
npx expo --version
# Upgrade to latest
npx expo install expo@latest
# Fix dependencies
npx expo install --fix
# Check for issues
npx expo-doctorFor Bare React Native
More involved:
# Update package.json
npm install react-native@0.73.0
# Or use the upgrade command
npx react-native upgrade 0.73.0This will prompt you to accept/reject changes to native files.
Step 3: Handle Native Files
The upgrade helper shows diffs for:
android/build.gradleandroid/app/build.gradleios/Podfileios/YourApp/AppDelegate.m
Apply changes carefully. Don't just copy-paste - merge them with your existing customizations.
Step 4: Clean Everything
After applying changes:
# Remove node_modules
rm -rf node_modules
npm install
# Android clean
cd android && ./gradlew clean && cd ..
# iOS clean
cd ios && rm -rf Pods Podfile.lock && pod install && cd ..
# Clear Metro cache
npx react-native start --reset-cacheStep 5: Fix Dependencies
Check for compatibility issues:
# List outdated packages
npm outdated
# Update compatible packages
npm update
# For specific packages that need major updates
npm install some-package@latestCommon Breaking Changes
React Native 0.72+
- Hermes is default (remove explicit Hermes config)
- New architecture support (optional)
React Native 0.71+
- TypeScript by default
- Flexbox gap support
- New app template
React Native 0.70+
- Hermes on iOS
- CMake for Android native builds
Dependency Compatibility Check
Before upgrading, check if key dependencies support the new version:
- react-native-reanimated
- react-native-gesture-handler
- react-navigation
- Any native modules you use
# Check a package's peer dependencies
npm info react-native-reanimated peerDependenciesStep 6: Test Everything
Create a testing checklist:
- [ ] App launches on iOS
- [ ] App launches on Android
- [ ] Navigation works
- [ ] API calls succeed
- [ ] Images load
- [ ] Animations are smooth
- [ ] Push notifications work
- [ ] Deep links work
- [ ] Release build worksRollback Plan
If things go wrong:
# Discard all changes
git checkout .
git clean -fd
# Go back to main
git checkout mainThis is why we use a branch.
Incremental Upgrades
Don't jump multiple major versions. Upgrade one version at a time:
0.68 → 0.69 → 0.70 → 0.71 → ...
Each step is smaller and easier to debug.
Expo SDK Upgrades
Expo makes this easier but still has gotchas:
# Upgrade SDK
npx expo install expo@^50.0.0
# This updates compatible packages automatically
npx expo install --fix
# Check for deprecated APIs
npx expo-doctorRead the SDK changelog for breaking changes.
When Things Break
Metro bundler errors
npx react-native start --reset-cacheiOS build fails
cd ios
rm -rf Pods Podfile.lock build
pod install --repo-updateAndroid build fails
cd android
./gradlew clean
./gradlew assembleDebug --stacktraceTypeScript errors after upgrade
Update types:
npm install @types/react@latest @types/react-native@latestMy Upgrade Checklist
- ✅ Read changelog thoroughly
- ✅ Check dependency compatibility
- ✅ Create upgrade branch
- ✅ Run upgrade helper
- ✅ Apply changes incrementally
- ✅ Clean build folders
- ✅ Test on both platforms
- ✅ Test release builds
- ✅ Test critical user flows
- ✅ Merge when confident
Take your time. Rushing an upgrade causes more problems than it solves.