React Native New Architecture Documentation

repository·main·Indexed 23 days ago

https://github.com/reactwg/react-native-new-architecture

Technical guides and migration workflows for the React Native New Architecture rollout. Includes documentation on enabling the New Architecture for apps and libraries, creating Fabric Native Components and Turbo Native Modules, using Codegen for type safety, and implementing backward compatibility for legacy components and modules.

Tokens
30K
Snippets
70
Records
108
Agent score
80%

What's inside react-native-new-architecture

  1. Access React Native New Architecture guides and documentation

    main

    The React Native New Architecture Working Group provides guides for enabling the New Architecture in apps and libraries, as well as workflows for creating Fabric Native Components and Turbo Native Modules.

    Note: Many guides in this repository are marked as deprecated. For the most up-to-date information, always refer to the official React Native website.

  2. What are Fabric Native Components

    main

    A Fabric Native Component is a native component rendered using the Fabric Renderer. Using Fabric instead of Legacy Native Components provides several benefits of the New Architecture:

    • Strongly typed interfaces: Consistent across platforms.
    • C++ support: Ability to write code in C++ (exclusively or integrated with native languages) to reduce platform-specific duplication.
    • JSI (JavaScript Interface): Enables more efficient communication between native and JavaScript code compared to the traditional bridge.

    Fabric Native Components are created starting from a JavaScript specification. Codegen then generates C++ scaffolding code to connect your component-specific logic to the React Native infrastructure. This C++ scaffolding is shared across all platforms.

  3. Use AppTurboModuleProvider to manage multiple C++ Turbo Modules

    main

    To avoid code duplication when adding multiple C++ Turbo Native Modules, you can implement an AppTurboModuleProvider. This provider acts as a factory that returns the appropriate module instance based on the requested name.

    1. Define AppTurboModuleProvider with a getTurboModule method.
    2. Implement getTurboModule to check the name and return a std::make_shared instance of your module.
    3. Register the provider in your platform-specific entry points (OnLoad.cpp for Android and AppDelegate.mm for iOS).
    #include "AppTurboModuleProvider.h"
    #include "NativeSampleModule.h"
    
    namespace facebook::react {
    
    std::shared_ptr<TurboModule> AppTurboModuleProvider::getTurboModule(
        const std::string& name,
        std::shared_ptr<CallInvoker> jsInvoker) const {
      if (name == "NativeSampleModule") {
        return std::make_shared<facebook::react::NativeSampleModule>(jsInvoker);
      }
      // Other C++ Turbo Native Modules for you app
      return nullptr;
    }
    
    } // namespace facebook::react
  4. Share logic between Legacy and Fabric Components using a ManagerImpl

    main

    To avoid duplicating business logic, create a shared implementation class (e.g., MyComponentViewManagerImpl) in the src/main directory. This class should contain the core logic for creating view instances and handling properties. Both the Legacy SimpleViewManager and the Fabric ViewManager can then call these shared methods.

    Java Example: Shared Implementation

    package com.mycomponent;
    
    import androidx.annotation.Nullable;
    import com.facebook.react.uimanager.ThemedReactContext;
    
    public class MyComponentViewManagerImpl {
    
        public static final String NAME = "MyComponent";
    
        public static MyComponentView createViewInstance(ThemedReactContext context) {
            return new MyComponentView(context);
        }
    
        public static void setFoo(MyComponentView view, String param) {
            // implement the logic of the foo function using the view and the param passed.
        }
    }
    package com.mycomponent;
    
    import androidx.annotation.Nullable;
    import com.facebook.react.uimanager.ThemedReactContext;
    
    public class MyComponentViewManagerImpl {
    
        public static final String NAME = "MyComponent";
    
        public static MyComponentView createViewInstance(ThemedReactContext context) {
            return new MyComponentView(context);
        }
    
        public static void setFoo(MyComponentView view, String param) {
            // implement the logic of the foo function using the view and the param passed.
        }
    }
  5. Supported types for JavaScript specs

    main

    When defining specs in Flow or TypeScript, you must use types that can be mapped one-to-one to native platform types.

    Supported Types:

    • Primitive types: string, number, boolean
    • Function types
    • Object types
    • Array types

    Unsupported Types:

    • Union types are not supported.

    Constraint: All types must be read-only.

    • Flow: Use + prefix, $ReadOnly<>, or {||} for objects.
    • TypeScript: Use readonly for properties, Readonly<> for objects, and ReadonlyArray<> for arrays.
  6. Understand New Architecture Terminology

    main

    To navigate guides for the New Architecture, use the following standard terminology:

    • Legacy Native Components/Modules: Components or Modules running on the old React Native architecture.
    • Fabric Native Components (Fabric Components): Components adapted for the new renderer in the New Architecture.
    • Turbo Native Modules (Turbo Modules): Modules adapted for the new Native Module System in the New Architecture.
  7. Understand the structure of generated Android Codegen files

    main

    Android Codegen generates files in both Java and C++ (JNI) to bridge the two environments.

    Turbo Native Modules

    • Java: A Java abstract class is generated in the java package with the same name as the TurboModule. This must be implemented by the JNI C++ implementation.
    • JNI (C++): Located in the jni folder. It includes an interface (e.g., MyTurbomodule.h) for JSI initialization and an implementation file (e.g., MyTurbomodule-generated.cpp) for JS/Native method invocation.

    Fabric Native Components

    • Java: Generates MyFabricComponentManagerInterface.java and MyFabricComponentManagerDelegate.java in the java package. These are used by the native MyFabricComponentManager to load the component at runtime.
    • JNI (C++): Contains the rendering layer. Includes ShadowNodes (representing the React entity), Props, EventEmitters, and ComponentDescriptors.h (required to get a handle on the component).

    Build Files

    Both Turbo Modules and Fabric Components include Android.mk and CMakeLists.txt in the jni folder, which are used by the Android app to build the external modules.

  8. Understand the structure of generated iOS Codegen files

    main

    When running Codegen for iOS, the output is organized under build/generated/ios.

    Turbo Native Modules

    Each module generates a folder containing:

    • An interface file (e.g., MyTurboModuleSpecs.h) used to initialize the JSI interface.
    • An implementation file with a -generated suffix (e.g., MyTurboModuleSpecs-generated.mm) containing the logic to invoke native methods between JS and native.

    Fabric Native Components

    Each component generates a folder containing:

    • ShadowNodes.h/cpp: Represents the node in the React abstract tree.
    • Props.h/cpp: Defines the component's props.
    • EventEmitters.h/cpp: Defines event emitters.
    • ComponentDescriptors.h: Used by React Native and Fabric to obtain a reference to the component.
    • RCTComponentViewHelpers.h: Contains helper methods and protocols for the Native View to respond to JSI invocations.

    Registry

    • RCTThirdPartyFabricComponentsProvider.h/mm: A registry used at runtime to retrieve the correct class for a required Fabric Native Component so React Native can instantiate it.

    Note: FBReactNativeSpec and rncore are core modules generated by React Native itself and will always be present.

  9. How React 18 concurrency relates to the New Architecture

    main

    React 18's concurrent features (like startTransition and Suspense) rely on a concurrent rendering engine that prepares multiple versions of the UI simultaneously.

    • Old Architecture: Cannot support concurrent rendering because it relies on mutating native trees, which is incompatible with preparing multiple UI versions at once.
    • New Architecture: Designed bottom-up with concurrent rendering in mind. It is fully compatible with React 18 and requires the use of Fabric Native Components and Turbo Native Modules to enable these features.
  10. Strategies for creating backward compatible modules

    main

    To ensure a library works in both the Old Architecture and the New Architecture, you should minimize the changes required for users to adopt the new version. This allows users to migrate to the New Architecture smoothly when they are ready.

    Achieving backward compatibility involves three main areas of focus:

    1. Update installation configuration: Avoid using code that is unnecessary for the Old Architecture.
    2. Update code for dual support: Use the mechanisms provided by Android and iOS build pipelines to provide a library that compiles correctly for the active React Native Architecture.
    3. Configure specs for implementation loading: Ensure the JavaScript layer leverages the New Architecture implementation when it is available.
  11. Support custom C++ types in Turbo Native Modules

    main

    By default, C++ Turbo Native Modules support most std:: standard types. To add support for new or custom types (e.g., folly::StringPiece, QString, boost::filesystem::path), you must provide a bridging header file that specializes the Bridging struct for your type.

    Your bridging header must include:

    1. An explicit specialization of the Bridging struct for your custom type.
    2. A fromJs function to convert from jsi:: types to your custom type.
    3. A toJs function to convert from your custom type to jsi:: types.

    Note: Omitting fromJs makes the type read-only from JS; omitting toJs makes it write-only.

  12. What are Turbo Native Modules

    main

    Turbo Native Modules are the next iteration of React Native Native Modules. Unlike the legacy bridge-based modules that rely on JSON serialization, Turbo Native Modules use the JavaScript Interface (JSI) for more efficient communication.

    Key benefits include:

    • Strongly typed interfaces: Consistent across platforms.
    • C++ support: Ability to write code in C++ to reduce platform duplication.
    • Lazy loading: Modules are loaded only when needed, improving app startup time.
    • JSI-based communication: Direct communication between JavaScript and native code, bypassing the bridge.