React Native New Architecture: 5 Core Patterns for Fabric Renderer and TurboModules

前端工程

React Native New Architecture: The Three Pillars of Performance Leap

The old architecture's async Bridge serialization overhead, layout calculation jank, and limited native module extensibility — React Native's performance bottlenecks have long been criticized. The new architecture achieves synchronous JSI calls, concurrent rendering, and type-safe bridging through Fabric renderer, TurboModules, and Codegen. In 2026, React Native new architecture is the default, and migration is no longer optional.

This article covers 5 core patterns, guiding you through Fabric rendering → TurboModules → Codegen → migration strategy → performance optimization.


Core Concepts

Concept Description
Fabric New renderer replacing old UI Manager
TurboModules New native module system replacing NativeModules
JSI JavaScript Interface, C++ synchronous call layer
Codegen Auto-generates C++/Java/ObjC bridging code
Shadow Tree Fabric's virtual tree supporting concurrent computation
Yoga Cross-platform layout engine
Event Pipeline New event system with priority scheduling
State Update Fabric state updates with batch commits

Problem Analysis: 5 Major New Architecture Migration Challenges

  1. C++ knowledge barrier: TurboModules and Fabric require C++ code
  2. Legacy library compatibility: Many third-party libraries not yet adapted
  3. Complex Codegen configuration: Type specs and code generation learning curve
  4. Changed debugging experience: New architecture debugging differs from old
  5. Difficult progressive migration: Issues with mixed old/new architecture runtime

Step-by-Step: 5 New Architecture Implementation Patterns

Pattern 1: TurboModule Native Module

// NativeCalculator.ts
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
  add(a: number, b: number): Promise<number>;
  multiply(a: number, b: number): number;
  getConstants: () => {
    PI: number;
    VERSION: string;
  };
}

export default TurboModuleRegistry.getEnforcing<Spec>('Calculator');
// CalculatorModule.java
@ReactModule(name = CalculatorModule.NAME)
public class CalculatorModule extends NativeCalculatorSpec implements TurboModule {
  public static final String NAME = "Calculator";

  @Override
  public double add(double a, double b) {
    return a + b;
  }

  @Override
  public double multiply(double a, double b) {
    return a * b;
  }

  @Override
  public Map<String, Object> getTypedExportedConstants() {
    return Map.of("PI", Math.PI, "VERSION", "2.0.0");
  }
}

Pattern 2: Fabric Custom Component

// CustomText.ts
import type { HostComponent } from 'react-native';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';

export interface NativeProps {
  text: string;
  fontSize?: number;
  color?: string;
  maxLines?: number;
}

export default codegenNativeComponent<NativeProps>('CustomText');
// CustomTextManager.java
public class CustomTextManager extends ViewGroupManager<TextView>
    implements CustomTextManagerInterface<TextView> {

  private final CustomTextManagerDelegate mDelegate = new CustomTextManagerDelegate(this);

  @Override
  public String getName() { return "CustomText"; }

  @Override
  protected TextView createViewInstance(ThemedReactContext reactContext) {
    return new TextView(reactContext);
  }

  @Override
  public void setText(TextView view, String text) { view.setText(text); }

  @Override
  public void setFontSize(TextView view, float fontSize) { view.setTextSize(fontSize); }

  @Override
  public CustomTextManagerDelegate getDelegate() { return mDelegate; }
}

Pattern 3: Codegen Configuration and Type Specs

// package.json
{
  "codegenConfig": {
    "name": "MyAppSpec",
    "type": "modules",
    "jsSrcsDir": "src/specs",
    "android": { "javaPackageName": "com.example.specs" }
  }
}
// src/specs/NativeStorage.ts
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
  getItem(key: string): Promise<string | null>;
  setItem(key: string, value: string): Promise<void>;
  removeItem(key: string): Promise<void>;
  getAllKeys(): Promise<string[]>;
}

export default TurboModuleRegistry.getEnforcing<Spec>('Storage');

Pattern 4: Event Emission and Priority Scheduling

// CustomViewManager.java
private void emitOnPress(ReactContext reactContext, int viewId) {
  reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
    viewId, "onPress", Arguments.createMap()
  );
}

private void dispatchEventWithPriority(ThemedReactContext context, int viewId) {
  EventDispatcher dispatcher = context.getNativeModule(UIManagerModule.class)
    .getEventDispatcher();
  dispatcher.dispatchEvent(new CustomPressEvent(viewId));
}

Pattern 5: Progressive Migration and Interop Layer

// app.json
{ "expo": { "newArchEnabled": true } }

// Check if new architecture is enabled
const isNewArch = global.__turboModuleProxy != null;
console.log('New Architecture:', isNewArch);

// Compatible with both architectures
const isTurbo = global.__turboModuleProxy != null;
const MyModule = isTurbo
  ? TurboModuleRegistry.getEnforcing<Spec>('MyModule')
  : NativeModules.MyModule;

Pitfall Guide

Pitfall 1: TurboModule return type mismatch

// ❌ Wrong: Codegen spec doesn't match implementation
export interface Spec extends TurboModule {
  getData(): string; // declared sync
}
// Java: returns Promise (actually async)

// ✅ Correct: keep consistent
export interface Spec extends TurboModule {
  getData(): Promise<string>; // async declaration
}

Pitfall 2: Fabric component not registered

// ❌ Wrong: created Manager but didn't register
public class CustomTextManager extends ViewGroupManager<TextView> { ... }

// ✅ Correct: register in Package
public class MyAppPackage extends BaseReactPackage {
  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return List.of(new CustomTextManager());
  }
}

Pitfall 3: C++ compilation errors

// ❌ Wrong: missing JSI header reference
#include <jsi/jsi.h> // path may be incorrect

// ✅ Correct: configure CMake properly
// CMakeLists.txt
target_include_directories(mymodule PRIVATE
  ${REACT_NATIVE_DIR}/ReactCommon/jsi
)

Pitfall 4: Ignoring thread safety

// ❌ Wrong: operating JS values outside JS thread
void callback(jsi::Runtime& rt) {
  std::thread([&rt]() {
    rt.global().setProperty(rt, "result", 42); // crash!
  }).detach();
}

// ✅ Correct: schedule back to JS thread via JSI dispatcher
void callback(jsi::Runtime& rt) {
  std::thread([this]() {
    runOnJSQueue([this](jsi::Runtime& rt) {
      rt.global().setProperty(rt, "result", 42);
    });
  }).detach();
}

Pitfall 5: Not handling old architecture fallback

// ❌ Wrong: assuming new architecture is always available
const module = TurboModuleRegistry.getEnforcing<Spec>('MyModule');

// ✅ Correct: compatible with both architectures
const isTurbo = global.__turboModuleProxy != null;
const MyModule = isTurbo
  ? TurboModuleRegistry.getEnforcing<Spec>('MyModule')
  : NativeModules.MyModule;

Error Troubleshooting

# Error Cause Solution
1 TurboModuleRegistry: MyModule could not be found Native module not registered Check Package registration and module name
2 Codegen error: type mismatch TS spec doesn't match implementation Unify Codegen type definitions and native implementation
3 C++ compilation error: jsi.h not found Header file path error Configure CMake include paths
4 ViewManager not found Fabric component not registered Register ViewManager in Package
5 Invariant Violation: new arch New architecture not enabled Set newArchEnabled=true
6 Event delivery failed Event name mismatch Check event name matches registration
7 JSI binding failed C++ binding initialization failed Check onLoad and install functions
8 Shadow node creation failed Yoga layout calculation error Check custom layout properties
9 Interop layer crash Legacy module bridging crash Upgrade legacy module or use compatibility layer
10 Build failed: NDK not found Android NDK not configured Install NDK and configure ANDROID_NDK

Advanced Optimization

  1. JSI direct ArrayBuffer manipulation: Zero-copy binary data transfer for image/audio processing
  2. Fabric Concurrent Layout: Enable concurrent layout computation to reduce main thread blocking
  3. Lazy TurboModule loading: Load native modules on demand to reduce startup time
  4. Custom ShadowNode: Implement complex layouts like waterfall, virtual lists
  5. C++ state sharing: Share C++ state via JSI, avoiding serialization overhead

Comparison

Dimension New Arch (Fabric) Old Arch (Bridge) Flutter KMP Compose
Rendering Performance ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
JS-Native Communication ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
Type Safety ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Ecosystem Compatibility ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
Learning Curve ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐
Cross-Platform Consistency ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐

Summary: React Native new architecture fundamentally solves old architecture performance bottlenecks through Fabric, TurboModules, and Codegen. The new architecture suits React Native projects seeking native performance, especially interaction-intensive apps. With the new architecture as default in 2026, migrate early for continued performance improvements and ecosystem support.


Online Tools

Try these browser-local tools — no sign-up required →

#React Native新架构#Fabric#TurboModule#JSI#2026#前端工程