Skip to main content

React Native New Architecture 2026: Fabric and TurboModules

·PkgPulse Team

React Native New Architecture in 2026: Fabric, TurboModules, and the Expo SDK Migration

TL;DR

The React Native New Architecture is no longer experimental — it's the default in React Native 0.76+ and Expo SDK 52+. The New Architecture replaces the legacy Bridge with JSI (JavaScript Interface), the legacy UI renderer with Fabric, and legacy native modules with TurboModules. For React Native developers in 2026, New Architecture is the table stakes: better performance, synchronous native calls, concurrent React support, and access to the modern API surface. The migration is well-supported with Expo's tooling, but some third-party npm packages still need to be audited for compatibility.

Key Takeaways

  • JSI (JavaScript Interface) replaces the async message bridge — JavaScript can now call native code synchronously without serializing to JSON
  • Fabric is the new UI renderer — re-implements all native components (View, Text, ScrollView, etc.) with better concurrency and React 18+ concurrent mode support
  • TurboModules is the new native modules system — lazy-loaded, typed via CodeGen, synchronous when needed
  • Expo SDK 52 (November 2024) enabled New Architecture by default — most Expo apps can adopt it with one config change
  • Package compatibility: ~85% of popular React Native packages on npm are New Architecture compatible in 2026; ~15% are still Bridge-only or have partial support
  • Performance gains: typical apps see 10-30% UI thread improvement; apps with heavy native module usage see up to 3x improvement in cross-thread call performance

The Legacy Architecture: What's Being Replaced

Before understanding what's new, understand what was broken with the old Bridge.

The Old Bridge Model

JavaScript Thread
       ↓ (async, serialized to JSON)
    Bridge
       ↓ (async, deserialized)
   Native Thread

Every cross-boundary call required:

  1. Serializing JavaScript values to JSON
  2. Passing the JSON over the async bridge
  3. Deserializing JSON on the native side
  4. Running the native code
  5. Serializing the result back to JSON
  6. Returning async across the bridge

This created three major problems:

  • Performance: Serialization/deserialization overhead on every call
  • Asynchrony: Native code couldn't be called synchronously, making certain patterns impossible
  • Concurrency: The legacy renderer couldn't support React 18's concurrent features (transitions, Suspense, useTransition)

What the New Architecture Fixes

JavaScript Thread
       ↓ (synchronous, via C++ JSI)
   JSI Layer (C++)
       ↓ (direct function calls)
   Native Thread

JSI is a C++ layer that sits between the JS engine (Hermes) and native code. JavaScript can call native functions directly — no serialization, no async, no bridge.


JSI: JavaScript Interface

JSI is the foundation everything else builds on. It's a C++ API that lets native code expose objects and functions directly to the JavaScript VM:

// Native side — exposing a synchronous function via JSI
auto multiply = jsi::Function::createFromHostFunction(
    runtime,
    jsi::PropNameID::forAscii(runtime, "multiply"),
    2,  // number of arguments
    [](jsi::Runtime& runtime,
       const jsi::Value& thisValue,
       const jsi::Value* arguments,
       size_t count) -> jsi::Value {
      double a = arguments[0].asNumber();
      double b = arguments[1].asNumber();
      return jsi::Value(a * b);  // Direct return, no async
    }
);

runtime.global().setProperty(runtime, "nativeMultiply", std::move(multiply));
// JavaScript side — synchronous call, no await needed
const result = global.nativeMultiply(5, 10);
console.log(result);  // 50 — synchronous!

What JSI Enables

JSI underpins several major improvements:

  • React Native Reanimated 3 uses JSI to run animations on the UI thread without bridge overhead — this is why Reanimated 3 animations are buttery smooth
  • MMKV (fast key-value storage) uses JSI for synchronous reads — MMKV.getString('key') is synchronous, unlike AsyncStorage
  • Vision Camera (camera frame processing) uses JSI to process frames in real-time without bridge overhead
  • React Native SQLite/WatermelonDB use JSI for synchronous database operations

Fabric: The New UI Renderer

Fabric is the complete rewrite of React Native's rendering pipeline. It implements the React reconciler natively in C++, enabling true concurrent rendering.

What Changes With Fabric

Shadow tree in C++: The previous architecture maintained the layout tree in JavaScript. Fabric moves this to C++, enabling:

  • Faster layout calculations (no JS ↔ native round-trips)
  • Synchronous layout reads (measure() is now synchronous)
  • React 18 concurrent mode support

Concurrent React support: With Fabric, React Native supports the same concurrent features as React DOM:

import { useTransition, Suspense } from 'react'

function ProductList() {
  const [isPending, startTransition] = useTransition()
  const [query, setQuery] = useState('')

  function handleSearch(text: string) {
    // Low-priority update — won't block the UI thread
    startTransition(() => {
      setQuery(text)
    })
  }

  return (
    <>
      <TextInput onChangeText={handleSearch} />
      {isPending && <ActivityIndicator />}
      <Suspense fallback={<LoadingSkeleton />}>
        <SearchResults query={query} />
      </Suspense>
    </>
  )
}

New Native Components

Fabric replaces all legacy native components. The new components (<View>, <Text>, <ScrollView>, etc.) are re-implemented in C++ and have subtle behavioral changes:

  • No more setNativeProps — direct prop mutation on native nodes is gone; use state
  • measureInWindow is synchronous — no more callback-based layout measurement for many use cases
  • Event handling is synchronous — touch events handled without bridge round-trips

TurboModules: The New Native Module System

TurboModules replaces the old NativeModules API. The key improvements:

Lazy Loading

Legacy native modules loaded ALL modules at startup. TurboModules loads modules on first use:

// Legacy: All native modules initialized at app startup (slows cold start)
import { NativeModules } from 'react-native'
const { MyCamera } = NativeModules  // Already initialized

// TurboModules: Loaded on first access (faster cold start)
import { TurboModuleRegistry } from 'react-native'
const MyCamera = TurboModuleRegistry.get('MyCamera')  // Loaded here

Type Safety via CodeGen

TurboModules use CodeGen to generate TypeScript types from native module specs:

// NativeMyModule.ts — the spec file
import type { TurboModule } from 'react-native'
import { TurboModuleRegistry } from 'react-native'

export interface Spec extends TurboModule {
  // CodeGen generates native bindings from this interface
  getDeviceName(): string  // Synchronous
  requestCameraPermission(): Promise<boolean>  // Async
  capturePhoto(quality: number): Promise<string>  // Returns file URI
}

export default TurboModuleRegistry.strictGet<Spec>('MyModule')

Expo SDK 52: New Architecture by Default

Expo SDK 52 (released November 2024) enabled New Architecture by default for all new projects. For existing projects:

Enabling in app.json

{
  "expo": {
    "newArchEnabled": true,
    "plugins": [
      "expo-router"
    ]
  }
}

That's it for most Expo apps — one config change. Expo's managed workflow handles the C++ compilation, Hermes configuration, and module linking automatically.

Verifying New Architecture is Active

// In your app — check at runtime
import { Platform } from 'react-native'

// Check if Fabric is enabled
const isFabricEnabled = global.nativeFabricUIManager != null

// Check if TurboModules are enabled
const isTurboModulesEnabled = global.__turboModuleProxy != null

console.log({ isFabricEnabled, isTurboModulesEnabled })

Running the Expo New Architecture Check

npx expo-doctor
# Reports compatibility issues:
# ✓ All 47 packages are compatible with Expo SDK 52
# ⚠ react-native-camera: not compatible with New Architecture
# ⚠ react-native-action-sheet: partial support

Package Compatibility in 2026

Most popular packages have added New Architecture support. Here's the state of key packages:

Fully Compatible (Green)

PackageStatusNotes
react-native-reanimated 3.xUses JSI natively
react-native-gesture-handler 2.xRequired for Fabric
react-native-screens 3.xNavigation
@shopify/flash-listHigh-perf lists
react-native-mmkvJSI-based storage
expo-cameraFull Fabric support
react-native-safe-area-contextRequired for Expo
@tanstack/react-queryPure JS, not affected
zustandPure JS, not affected

Partially Compatible (Yellow)

PackageStatusNotes
react-native-maps⚠️Works but limited
react-native-camera⚠️Use expo-camera instead
react-native-blur⚠️Use @react-native-community/blur
react-native-linear-gradient⚠️Use expo-linear-gradient
react-native-svg 13+Fixed in v13

Not Yet Compatible (Red — Avoid)

Check the React Native Directory for real-time compatibility status. For any package showing "New Architecture: Unsupported", consider:

  1. Using the Expo equivalent (if it exists)
  2. Finding a community fork with New Architecture support
  3. Using the Interop Layer as a temporary bridge

The Interop Layer

React Native 0.74+ includes an Interop Layer that lets legacy Bridge modules work alongside New Architecture. It's enabled by default:

// react-native.config.js
module.exports = {
  project: {
    ios: {},
    android: {},
  },
  // Legacy modules automatically work via Interop Layer
  // You can disable per-package if causing issues:
  unstable_enableNewArchInterop: true,
}

The Interop Layer is a compatibility shim — it translates Bridge calls to the new system. Performance is slightly worse than native New Architecture modules, but it allows gradual migration.


Migration Strategy for Existing Apps

Step 1: Audit Your Dependencies

# Use React Native Upgrade Helper or expo-doctor
npx react-native doctor

# For Expo apps
npx expo-doctor

# Manual check — list all native modules
cat package.json | grep react-native | grep -v '"react-native"'

Step 2: Update to React Native 0.76+ or Expo SDK 52+

# Expo managed workflow
npx expo install expo@^52 --fix
npx expo install

# Bare React Native
npx react-native upgrade

Step 3: Enable New Architecture

Expo (app.json):

{ "expo": { "newArchEnabled": true } }

Bare React Native (android/gradle.properties):

newArchEnabled=true

Bare React Native (ios/Podfile):

ENV['RCT_NEW_ARCH_ENABLED'] = '1'

Step 4: Fix Compatibility Issues

Common migration issues and fixes:

// ❌ setNativeProps is removed
ref.current?.setNativeProps({ style: { opacity: 0.5 } })

// ✅ Use state/animated values instead
const opacity = useRef(new Animated.Value(1)).current
Animated.timing(opacity, { toValue: 0.5, duration: 300, useNativeDriver: true }).start()

// ❌ findNodeHandle deprecated
const node = findNodeHandle(ref.current)

// ✅ Use ref directly
ref.current?.measure((x, y, width, height) => { ... })

Performance Benchmarks

Real-world measurements comparing Old vs New Architecture on a mid-range Android device (Pixel 6a):

MetricOld ArchitectureNew ArchitectureImprovement
App cold start (complex app)1,850ms1,420ms23% faster
List scroll FPS (1000 items)45fps59fps31% smoother
Animation start latency32ms8ms75% reduction
Native module call (sync via JSI)12ms (async)0.2ms (sync)60x faster
JS bundle eval280ms250ms11% faster

Methodology

  • React Native version: 0.76.x, Expo SDK 52.x
  • Package compatibility data from React Native Directory (reactnative.directory), March 2026
  • Benchmark data from community performance reports and Meta's official New Architecture blog posts
  • Sources: React Native official docs (reactnative.dev), Expo documentation (docs.expo.dev), JSI documentation

Compare React Native packages on PkgPulse — filter by New Architecture compatibility status and download trends.

Related: Expo Router vs React Navigation vs Solito 2026 · React Native Reanimated vs Moti vs Skia Animation Libraries 2026 · Expo SQLite vs WatermelonDB vs Realm React Native 2026

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.