With the evolution of React Native, the New Architecture brings significant performance and maintainability improvements through features like TurboModules, Fabric, and C++ shared logic. Upgrading to this architecture can seem intimidatingโbut with the right strategy, it's achievable.
In this blog, Iโll walk you through two practical approaches to upgrading your project to the New Architecture in React Native (v0.79.3 at the time of writing), the recommended approach, the challenges I faced, and how I overcame them.
In this guide, Iโll walk you through:
- โ Two practical upgrade approaches
- ๐ ๏ธ The recommended method
- โ๏ธ Challenges I faced
- ๐ก How I solved them
- ๐ ๏ธ Solutions to Each Problem
- โ Migration Checklist
- ๐ซ Common Mistakes to Avoid
- ๐ Final Checklist Before You Go Live
๐ When Should You Consider Upgrading?
If your current project is within 2 to 4 versions of the latest release, upgrading is relatively safe. Otherwise, itโs better to migrate code manually to a fresh project. Weโll cover both methods.
๐ From 0.71.0 to 0.79.3: My New Architecture Journey
I upgraded from React Native 0.71 to 0.79 for New Architecture support
๐ ๏ธ Approach 1: Upgrade Using React Native Upgrade Helper (Recommended for Small Version Gaps)
This method is ideal if your current version is just a few versions behind (e.g., 0.75 to 0.79).
Step 1. Update Android Studio
- Make sure youโre using the latest stable version of Android Studio.
- This ensures compatibility with the updated Gradle, SDKs, and React Native tooling.
Step 2. Use the React Native Upgrade Helper
- Visit React Native Upgrade Helper.
- Select your current version (left) and target version (right, e.g., 0.79.3).
Step 3. Follow the Diff Instructions Carefully
- Pay special attention to native file changesโthese are critical for enabling the New Architecture.
- Use version control to commit incrementally and rollback if needed.
๐ฆ Update Third-Party Dependencies
Once youโre on the latest version, update your dependencies:
- Visit React Native Directory
- Apply the filter: "Supports New Architecture"
- Replace or upgrade libraries accordingly
โ Approach 2: Create a Fresh Project (Recommended for larger Version Gaps)
If your current project is outdated or complex, this is the safest and cleanest way to upgrade.
๐งฑ Steps to Migrate
Step 1. Create a New Project
npx @react-native-community/cli init MyApp
Step 2. Migrate Your Existing Codebase
Once your new React Native project is created (preferably using the latest stable version like v0.79.3), itโs time to bring your existing app logic into the new environment.
๐ Step 3: Move Your src/
Folder
Start by copying the entire src
directory from your old project into the root of the new project
๐ฆ Step 4: Sync and Install Dependencies
Now, open both the old and new package.json
files side by side.
- Carefully review the dependencies and devDependencies.
- Instead of copying everything directly, manually install each package in the new project using the latest version.
- Ensure that each dependency you bring in is compatible with React Native's New Architecture.
Yes, it's manualโbut it's also bulletproof for both Android and iOS
โ Step 5: Verify It Works
After you've copied your source code and installed the updated dependencies:
- Clean the Android build (optional but recommended):
cd android && ./gradlew clean && cd ..
- Run the app on both platforms to ensure everything is wired correctly:
npx react-native run-android npx react-native run-ios
- Watch the terminal and device logs for any errors, warnings, or compatibility issues.
๐ก Tip: If any dependency causes issues with the new architecture, check the package's documentation or GitHub issues. Some packages may still require legacy support or additional configuration to work correctly.
๐งฉ Challenges I Faced (And How I Solved Them)
As I migrated to the New React Native Architecture, I ran into some unexpected issues that werenโt immediately obvious. Here's a breakdown of the most common ones โ and how I resolved each.
๐ฅCommon Issues (React Native New Architecture)
๐ก Note: Iโve included dedicated solution links at the end of this section for deeper dives.
๐1. Translation failed
The old way of handling translations using i18n-js
no longer works reliably in the new architecture.
โ
The recommended and stable alternative is react-i18next
, which is modern, flexible, and actively maintained.
โ๏ธ2. Redux not working
Redux can break in the new architecture, especially if you're using older packages like 'redux'
and 'redux-thunk'.
The new approach uses the modern Redux Toolkit:
import { configureStore } from "@reduxjs/toolkit";
๐ You donโt need to refactor your entire Redux logic.
Just update your store configuration. Actions, reducers, and selectors will continue to work as before.
Replace this
import {createStore, applyMiddleware, compose} from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './rootReducer'; const composeStore = compose(applyMiddleware(thunk)); export const appStore = createStore(rootReducer, composeStore); const store = () => { return appStore; }; export default store;
With this
import {configureStore} from "@reduxjs/toolkit"; import rootReducer from "./rootReducer"; export const appStore = configureStore({ reducer: rootReducer, devTools: true, middleware: getDefaultMiddleware => getDefaultMiddleware(), }); const store = () => { return appStore; }; export default store;
After integrating this, You might getting this redux error
Fix:
... middleware: getDefaultMiddleware => getDefaultMiddleware({ serializableCheck: false, }), ...
๐จ Final Note
By applying this fix, Redux may work as before.
But keep in mind โ this is only a temporary workaround.
๐ You should migrate your store setup to Redux Toolkit for long-term stability and compatibility with the new React Native architecture.
๐3. Absolute imports fail
If youโre using absolute import paths like @abc/screens
defined in package.json
, you may find they donโt resolve properly in the new architecture setup.
๐ ๏ธ In my case, I had to temporarily fall back to relative paths like:
import MyScreen from '../../screens/MyScreen';
โ Later, I fixed this properly by configuring
babel.config.js
andtsconfig.json
.
(I'll walk through that fix in a later section.)
4. Bridging fails
With the New Architecture, React Native introduces a bridge-less communication model.
This means:
- Legacy native modules written using the old bridge might stop working.
- You must migrate to TurboModules, define
spec
files, and rely on codegen for typed module integration.
While itโs more strict, it brings better performance, type safety, and native interoperability.
5. GIFs Fail to Load (New Architecture Compatibility)
If your app uses GIFs, they may not work properly with the New Architecture (Fabric/TurboModules).
Fix:
Add the Fresco GIF dependency to app/build.gradle:
implementation 'com.facebook.fresco:animated-gif:3.6.0'
โ ๏ธ Note: If 3.6.0 is not compatible, use the latest stable version of Fresco instead.
6. SafeAreaView Overlaps Status Bar on Android 15+ (Edge-to-Edge Issues)
If your app's content overlaps the status bar or edge-to-edge display isn't working properly on Android 15+, try this solution.
Fix:
Add this line to your Android /android/app/src/main/res/values/styles.xml
<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
7. react-native-linear-gradient
Padding Not Applying
When adding padding directly to the <LinearGradient>
component, it wonโt work as expected.
Instead, wrap your content in a <View>
and apply padding to that <View>
.
Fix
<LinearGradient colors={[COLORS.COLOR_ED0101, COLORS.COLOR_B60101]} style={styles.gradient} > <View style={{paddingHorizontal: 20, paddingVertical: 20}}> <Text>Your text</Text> </View> </LinearGradient>
8. Custom Font Not Working on iOS
Some custom fonts may not render correctly on iOS due to font family and weight handling in RCTFontUtils.mm.
Modify the file:
packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm
if (fontNames.count == 0) { font = [UIFont fontWithName:fontProperties.family size:effectiveFontSize]; if (!font) { font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight]; } } else { CGFloat closestWeight = INFINITY; for (NSString *name in fontNames) { UIFont *fontMatch = [UIFont fontWithName:name size:effectiveFontSize]; if (RCTGetFontStyle(fontMatch) != fontProperties.style) { continue; } CGFloat testWeight = RCTGetFontWeight(fontMatch); if (ABS(testWeight - fontProperties.weight) < ABS(closestWeight - fontProperties.weight)) { font = fontMatch; closestWeight = testWeight; } } if (!font) { font = [UIFont fontWithName:fontNames[0] size:effectiveFontSize]; } }
GitHub Reference: PR #47691
Problem | Solution |
---|---|
๐ i18n Translations not working | Multi-language Setup Guide |
โ๏ธ Redux not working | Redux Integration Tutorial |
๐ Absolute imports fail | Absolute Imports Fix |
๐ Native Bridging fails | TurboModules Guide โข C++ Guide |
๐ผ๏ธ GIFs not loading | implementation 'com.facebook.fresco:animated-gif:3.6.0' |
๐ผ๏ธ Layout overlapping | <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item> |
๐จ LinearGradient padding issue | Wrap content in <View> and apply padding to <View> instead of <LinearGradient> . |
๐ Custom font not rendering on iOS | Patch RCTFontUtils.mm to handle font names and weights more reliably. GitHub Ref |
๐ง Platform-Specific Challenges (Android & iOS)
While migrating to the New Architecture, I ran into some platform-specific issues โ especially on Android and iOS. Below are the key problems I faced, and how I resolved them.
Android
๐ฆ APK Size Increased
After upgrading to the New Architecture, I noticed the APK size increased significantly:
Version | APK Size |
---|---|
๐ง Before Upgrade | 112 MB |
๐ After Upgrade | 140 MB |
However, with a simple tweak, I was able to bring it down drastically โ my final APK was just 65 MB.
โ ๏ธ Important: After applying this change, make sure to test your appโs performance and launch time thoroughly.
There have been community discussions mentioning that settingandroid:extractNativeLibs="true"
might slightly impact launch performance.
In my case, I carefully compared app launch behavior before and after the change โ and found no noticeable difference in performance.
โ Solution
Update your AndroidManifest.xml
to include the following inside the <application>
tag:
<application android:extractNativeLibs="true" ... >
This ensures unused native libraries are not bundled unnecessarily.
๐ Proguard Build Failure
If youโre using Proguard or enabling minifyEnabled
, you may see this common R8 error:
๐ Fix Steps
1. Open the file:
๐ก Note: Make sure to build your release APK first โ otherwise, the missing_rules.txt file will not be generated.
android/app/build/outputs/mapping/release/missing_rules.txt
2. Copy the suggested rules from that file.
3. Paste them into android/app/proguard-rules.pro:
# Added from R8 missing rules -keep class com.example.SomeClass { *; } -dontwarn com.example.OtherClass
๐ If you already have custom Proguard rules, merge them carefully to avoid breaking your release build.
๐ Reference: React Native GitHub Issue #36505
Android Double Splash issue
Soulution
1. Create a custom splash drawable
Inside your project, create the file:
android/app/src/main/res/drawable/splash_screen.xml
Add the following code:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Background that matches React Native splash screen --> <item> <shape android:shape="rectangle"> <solid android:color="#000000" /> </shape> </item> <!--app logo centered (optional - remove if you just want solid color) --> <!-- <item> <bitmap android:gravity="center" android:src="@mipmap/ic_launcher" /> </item> --> </layer-list>
2. Update styles.xml
Open android/app/src/main/res/values/styles.xml
and add:
<item name="android:windowBackground">@drawable/splash_screen</item> <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimary</item>
This ensures that the splash screen defined in splash_screen.xml is used as the window background, preventing the double splash issue on Android.
๐ iOS-Specific Setup Issues
While running pod install
, I ran into the following CocoaPods and build error:
โ Solution
Edit your Podfile as follows:
platform :ios, '15.1' # Add this use_modular_headers! # Add this target 'YourAppName' do config = use_native_modules! # โโโ Add this block โโโ $RNFirebaseAsStaticFramework = true use_frameworks! :linkage => :static pod 'Firebase', :modular_headers => true pod 'FirebaseCoreInternal', :modular_headers => true pod 'GoogleUtilities', :modular_headers => true pod 'FirebaseCore', :modular_headers => true # โโโ End โโโ use_react_native!(...) end
Then run:
cd ios && pod install
This ensures compatibility with Firebase and other modular dependencies when using the new architecture.
iOS Double Splash issue
1. Open LaunchScreen.storyboard
Path: ios/YourApp/LaunchScreen.storyboard
If the file doesnโt exist, create a new LaunchScreen.storyboard in Xcode (File โ New โ File โ User Interface โ Storyboard).
2. Set Background Color
- Select the main View in Interface Builder.
- In the Attributes Inspector, set the Background color (e.g., black #000000 to match Android).
3. Add App Logo (ImageView)
- Drag an Image View onto the center of the screen.
- In the Attributes Inspector, set the image to your logo (e.g., AppLogo or LaunchIcon).
-
Use Auto Layout to center it:
- Select the Image View โ Add constraints โ Horizontally & Vertically in Container.
- Optionally set width/height constraints to keep logo size consistent.
4. Add Logo Asset
- Place your splash/logo image inside ios/YourApp/Images.xcassets.
- Name it (e.g., AppLogo).
- Make sure it has @1x, @2x, and @3x versions for all devices.
5. Set LaunchScreen in Project Settings
- In Xcode โ Project Navigator โ Select your project โ General tab.
- Under App Icons and Launch Images, set Launch Screen File to LaunchScreen.storyboard.
Example (Storyboard XML snippet)
If you prefer raw XML editing instead of Xcode UI, your LaunchScreen.storyboard could look like this (simplified):
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" initialViewController="ViewControllerID"> <scenes> <!-- Launch Screen --> <scene sceneID="LaunchScene"> <objects> <viewController id="ViewControllerID" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="ViewID" userLabel="LaunchView"> <rect key="frame" x="0.0" y="0.0" width="414" height="896"/> <color key="backgroundColor" systemColor="blackColor"/> <subviews> <imageView contentMode="scaleAspectFit" image="AppLogo" translatesAutoresizingMaskIntoConstraints="NO" id="LogoID"/> </subviews> <constraints> <constraint firstItem="LogoID" firstAttribute="centerX" secondItem="ViewID" secondAttribute="centerX" id="c1"/> <constraint firstItem="LogoID" firstAttribute="centerY" secondItem="ViewID" secondAttribute="centerY" id="c2"/> </constraints> </view> </viewController> </objects> </scene> </scenes> </document>
๐ My Recommendation:
If your current version is significantly outdated or your project is complex, start with a fresh React Native project and migrate your code manually. It may take more time initially, but the result is a leaner, faster, and more future-proof application.
If you're planning to upgrade to the New Architecture, here's what I suggest based on your current version gap:
๐ Scenario 1: Large Version Gap (e.g., RN 0.68 โ 0.79)
๐ง Recommendation:
If your current React Native version is significantly outdated, it's best to:
๐ Start fresh with a clean React Native project, and manually migrate your screens, logic, and assets.
This ensures a smoother transition without the risk of legacy code breaking under the new system.
Yes, it takes a bit more time โ but it pays off with a cleaner and more maintainable codebase.
๐ Scenario 2: Small Version Gap (e.g., RN 0.75 โ 0.79)
โ๏ธ Recommendation:
If the gap between your current version and the latest one is just 2โ4 versions, you can safely use the React Native Upgrade Helper or the official upgrade tool.
These tools help you compare file-by-file changes and apply only the necessary updates โ saving time while avoiding full rewrites.
โ๏ธ Choose the upgrade approach that matches your projectโs stability and complexity. Donโt rush it โ test thoroughly before shipping!
โ Migration Checklist & Tools
Hereโs a handy checklist and toolset to help guide your upgrade to the React Native New Architecture:
๐งฐ Tools You'll Need
Tool | Purpose |
---|---|
๐ Upgrade Helper | Compare file-by-file differences between RN versions |
โ๏ธ React Native CLI | Create fresh React Native projects |
๐ฆ React Native Directory | Check if libraries support the New Architecture (TurboModules/Fabric) |
๐ Migration Checklist
- ๐ Audit your current React Native version and all dependencies
- ๐ฑ Update to the latest Android SDK and compile/target versions
- ๐ค Decide: Upgrade in-place or create a fresh new RN project
- ๐ Update your Podfile, build.gradle, and overall project configs
- ๐ Enable the New Architecture (app.build.gradle + Podfile flags)
- ๐งฌ Migrate native modules to TurboModules (if applicable)
- ๐ Switch from i18n-js to react-i18next for translations
- โ๏ธ Update Redux store using @reduxjs/toolkit
- ๐ Fix absolute imports via babel.config.js and tsconfig.json
- ๐ฆ Optimize APK size using android:extractNativeLibs="true"
- ๐งช Test app performance and launch time thoroughly
- ๐ Fix Proguard errors using missing_rules.txt
- โ Validate both APK and IPA builds before production release
๐ซ Common Mistakes to Avoid
โ Mistake | โ ๏ธ Why It's a Problem | โ What To Do |
---|---|---|
Skipping clean builds | Cached files can cause unexpected crashes or outdated behavior | Run npx react-native clean and ./gradlew clean |
Ignoring native code | Legacy native modules may break under the New Architecture | Refactor to TurboModules using proper spec.ts and bridging format |
Not updating Android/iOS versions | Incompatible SDK versions can break builds | Use compileSdkVersion = 34 (or latest) and platform :ios, '15.1' |
Forgetting New Architecture flags | TurboModules/Fabric wonโt be enabled just by upgrading | Enable manually in gradle.properties , build.gradle , and Podfile |
Using outdated libraries | Many libraries are not compatible with the New Architecture | Check reactnative.directory before installing any library |
Ignoring Proguard + release builds | App might crash only in release mode without clear error logs | Test release builds early and copy missing rules from missing_rules.txt into proguard-rules.pro |
Testing only on emulators | Emulators donโt reflect real performance, launch time, or device-specific bugs | Always test on real devices (both Android & iOS) |
Skipping the docs | Missing official changes can cause implementation mistakes | Follow React Native New Architecture docs |
โ ๏ธ Note:
The issues and solutions Iโve shared are based on my specific project setup.
You might face different roadblocks depending on your architecture, packages, and integrations.
Always validate each solution with your own setup, and donโt hesitate to tweak things accordingly.
๐ Final Checklist Before You Go Live:
- โ Clean build (npx react-native clean & ./gradlew clean)
- โ New Architecture flags enabled (TurboModules, Fabric)
- โ Native modules migrated or verified
- โ Absolute imports working via Babel & tsconfig
- โ Translations updated (i18n-js โ react-i18next)
- โ Redux store migrated to @reduxjs/toolkit
- โ Real device testing (Android + iOS)
- โ Proguard rules added from missing_rules.txt
- โ APK & IPA thoroughly tested
- โ Android/iOS SDK versions updated
๐ Need Help?
Let me know in the comments if youโre stuck or hit something weird โ Iโd love to help or even update this guide to cover your case.
๐ Your Turn!
Have you upgraded your React Native version yet?
๐ Share the challenges you faced and how you solved them in the comments.
Letโs build a helpful community knowledge base together! ๐ฌ๐ฅ
๐ฏ Final Thoughts
Upgrading to the New Architecture isnโt just about bumping a version โ itโs a complete shift in how React Native communicates with native code.
If you're aiming for long-term stability, performance, and scalability, embracing this architecture with a clean slate may be the best move.
๐ Wrapping Up
Migrating to the New Architecture in React Native isnโt just about flipping a switch โ itโs about adopting a modern, more efficient way to build native apps with better performance, maintainability, and future compatibility.
Yes, it comes with its fair share of gotchas, but once you overcome those, the rewards are worth it ๐
Top comments (0)