
upgrade-react-native
โ Officialโ 7,136by shopify ยท part of shopify/flash-list
Upgrade the React Native fixture app to a new version. Covers JS deps, Android (Gradle, Kotlin, SDK), iOS (Podfile, pbxproj), Metro config, and third-party libraries.
This is the playbook your agent receives when the skill activates โ you don't need to read it to use the skill, but it's here to audit before installing.
Upgrade React Native Fixture App
Overview
The fixture app lives in fixture/react-native/. It is the primary test vehicle for FlashList on iOS and Android. The web fixture (fixture/web/) uses Expo and is independent โ check it builds after the upgrade but it does not need the same dependency changes.
Step 1 โ Research the Target Version
-
Check the latest stable RN version:
npm view react-native@latest version -
Use the rn-diff-purge repo to see the exact template diff between your current and target version:
https://raw.githubusercontent.com/react-native-community/rn-diff-purge/release/<version>/RnDiffApp/<file>Key files to fetch:
package.jsonโ React version, CLI versions, dev dep versionsandroid/build.gradleโ SDK versions, Kotlin versionandroid/app/build.gradleโ plugin names, dependency patternsandroid/gradle.propertiesโ feature flags (newArch, hermes, edgeToEdge)android/gradle/wrapper/gradle-wrapper.propertiesโ Gradle versionandroid/settings.gradleโ plugin management patternandroid/app/src/main/java/com/rndiffapp/MainApplication.ktโ app initialization patternios/Podfileโ pod configuration, post_install hooksios/RnDiffApp/AppDelegate.swiftโ app delegate patternmetro.config.jsโ Metro config API changes
-
Check third-party library compatibility with the target RN version:
react-native-reanimatedโ check compatibility tablereact-native-gesture-handlerโ supports 3 latest RN minorsreact-native-screens,react-native-safe-area-contextโ usually latest works@react-navigation/*โ check for breaking changes- Any image library (
@d11/react-native-fast-image, etc.)
Step 2 โ Update Dependencies
fixture/react-native/package.json
Update in this order:
reactandreact-nativeโ match the template@react-native/*dev packages โ must match the RN minor (e.g.,@react-native/babel-preset@0.84.1for RN 0.84.1)@react-native-community/cli*โ match the template- Third-party native libraries โ bump to versions compatible with the target RN
- Any new peer dependencies (e.g., reanimated 4 requires
react-native-worklets)
Babel config
Check if any Babel plugins moved packages. Example: reanimated 4 moved react-native-reanimated/plugin to react-native-worklets/plugin.
Metro config
Metro's internal module paths change between versions. Common breakage:
metro-config/src/defaults/exclusionListโ in newer Metro this moved tometro-config/private/defaults/exclusionListand exports a.defaultinstead of a direct function- Always verify the import works:
node -e "console.log(typeof require('<path>'))"
Step 3 โ Update Android
android/build.gradle
buildToolsVersion,compileSdkVersion,targetSdkVersionโ match templatekotlinVersionโ match templatendkVersionโ match template (usually unchanged between minors)
android/gradle/wrapper/gradle-wrapper.properties
- Update Gradle distribution URL to match template
android/gradle.properties
- Remove deprecated flags (e.g.,
android.enableJetifier,FLIPPER_VERSION) - Add new flags (e.g.,
edgeToEdgeEnabled) - Update JVM args if template changed them
android/app/build.gradle
- Update plugin names if changed (e.g.,
kotlin-androidโorg.jetbrains.kotlin.android) - Remove unused imports (e.g.,
import com.android.build.OutputFile) - Check
autolinkLibrariesWithApp()is present
android/settings.gradle
- Match template structure
- Remove manual project includes for pure-JS libraries (flash-list has no native Android code)
MainApplication.kt
- This changes significantly between major RN versions. Always diff against the template.
- Preserve custom code:
AppPackage()registration andI18nUtil.allowRTL()for RTL support. - Key pattern changes across versions:
- 0.79:
SoLoader.init()+DefaultNewArchitectureEntryPoint.load()+ReactNativeHost - 0.84:
loadReactNative(this)+getDefaultReactHost()with lazy delegate (no ReactNativeHost)
- 0.79:
Step 4 โ Update iOS
ios/Podfile
- Match template structure
- Remove deprecated env vars (e.g.,
ENV['RCT_NEW_ARCH_ENABLED']when new arch is the default) - Remove deprecated helper calls (e.g.,
get_default_flags()) - Keep project-specific customizations (
use_frameworks! :linkage => :staticif needed)
ios/FlatListPro.xcodeproj/project.pbxproj
- Update
IPHONEOS_DEPLOYMENT_TARGETto match the RN minimum (e.g., 15.1 for RN 0.76+) - Pod install will update header search paths and build settings automatically
ios/FlatListPro/Info.plist
- Add any new required plist keys (e.g.,
RCTNewArchEnabled)
Clean install
cd fixture/react-native
rm -rf node_modules yarn.lock
yarn install
cd ios && rm -rf Pods Podfile.lock && pod install && cd ..Step 5 โ Build and Verify
Build the flash-list library first
yarn build # from repo root โ compiles src/ โ dist/iOS
cd fixture/react-native
xcodebuild -workspace ios/FlatListPro.xcworkspace -scheme FlatListPro \
-configuration Debug -sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 16 Pro' buildAndroid
cd fixture/react-native
yarn react-native run-androidWeb
cd fixture/web && yarn install && npx expo export --platform webStep 6 โ Run Tests
Unit tests
yarn test # from repo root โ 181+ tests must passE2E tests (iOS)
cd fixture/react-native
yarn e2e:build:ios
yarn e2e:test:iosScreenshot reference updates: Visual diff tests (e.g., Carousel orientation) will fail after an RN upgrade because rendering changes slightly. To regenerate references:
- Delete the old reference directory (e.g.,
e2e/artifacts/ios/Carousel_landscape/) - Run the test โ it creates a new reference and fails with "no reference present"
- Run again โ it passes using the new reference
- Repeat for each failing screenshot (the test stops at the first missing reference per run)
Common Pitfalls
- Metro
exclusionListimport โ Metro's internal API paths change between versions. Always verify the import resolves before starting Metro. - Stale Metro on wrong port โ Kill ALL Metro instances before testing. Another project's Metro on a different port can cause "version mismatch" errors if the app connects to it.
react-native-reanimatedmajor version โ Major bumps (3โ4) require Babel plugin changes and may add new peer dependencies (react-native-worklets).- Gradle version jumps โ RN upgrades often bump Gradle (e.g., 8.xโ9.x). This can break custom Gradle scripts. Check build warnings for deprecations.
IPHONEOS_DEPLOYMENT_TARGETโ Must match or exceed the RN minimum. Pod install updates most settings, but the project-level target in pbxproj must be set manually.Info.plistnew keys โ Some RN versions require new plist entries (e.g.,RCTNewArchEnabled). Check the template's Info.plist diff.- Legacy arch removal โ Starting with RN 0.82+, legacy architecture code is being removed. Ensure all dependencies support new arch.
npx skills add shopify/flash-list --skill "upgrade-react-native" --full-depthRun this in your project โ your agent picks the skill up automatically.
No common issues documented yet. If you hit a problem, the repository's GitHub Issues page is the best place to look.
Licensed under MITโ you can use, modify, and redistribute it under that license's terms.
View the full license file on GitHub โ