Skip to content

A collection of sample React Native Apps that will show you how to use the New Architecture (Fabric & TurboModules) step-by-step.

License

Notifications You must be signed in to change notification settings

react-native-community/RNNewArchitectureApp

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RUN

This branch contains all the step executed to:

  1. Create an App starting from the version 0.67.4
  2. Migrate it to React Native 0.70.0, adopting the New Architecture.
  3. Create a TurboModule.
  4. Create a Fabric Component.

Table of Content

Steps

  1. npx react-native@0.67.4 init AwesomeApp --version 0.67.4
  2. cd AwesomeApp
  3. npx react-native start (in another terminal)
  4. npx react-native run-ios
  5. npx react-native run-android
  1. cd AwesomeApp
  2. yarn add react@18.0.0 to upgrade to React18
  3. yarn add react-native@0.70.0-rc.0
  4. Open the AwesomeApp/ios/AwesomeApp/AppDelegate.m file and update it as it follows:
        - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
        {
        #if DEBUG
    -       return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
    +       return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
        #else
            return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
        #endif
        }
  5. Open the ios/Podfile file and update it as it follows:
    - platform :ios, '11.0'
    + platform :ios, '12.4'
  6. At the same level of the AwesomeApp.xcodeproj, create an .xcode.env file with this content:
    export NODE_BINARY=$(command -v node)
    
    Eventually, replacing the $(command -v node) with the actual path to node.
  7. cd ios
  8. bundle exec pod install
  9. Open the android/build.gradle file and update the buildscript.ext block with the following code
    buildscript {
        ext {
            buildToolsVersion = "31.0.0"
            minSdkVersion = 21
            compileSdkVersion = 31
            targetSdkVersion = 31
            if (System.properties['os.arch'] == "aarch64") {
                // For M1 Users we need to use the NDK 24 which added support for aarch64
                ndkVersion = "24.0.8215888"
            } else {
                // Otherwise we default to the side-by-side NDK version from AGP.
                ndkVersion = "21.4.7075529"
            }
        }
    }
  10. Open the android/app/src/main/AndroidManifest.xml file and add this line:
    android:windowSoftInputMode="adjustResize"
    + android:exported="true">
    <intent-filter>
  11. Open the android/app/build.gradle and add the following function:
    def isNewArchitectureEnabled() {
        // To opt-in for the New Architecture, you can either:
        // - Set `newArchEnabled` to true inside the `gradle.properties` file
        // - Invoke gradle with `-newArchEnabled=true`
        // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
        return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
    }
  12. Open the android/gradle.properties and add the newArchEnabled=true property to it.
  13. npx react-native run-ios && npx react-native run-android
  1. Open the AwesomeApp/ios/AwesomeApp.xcworkspace in Xcode
  2. Rename all the .m files to .mm:
    1. main.m will be renamed to main.mm
    2. AppDelegate.m will be renamed to AppDelegate.mm
  3. Run npx react-native run-ios

Note: Renaming files in Xcode also updates the xcodeproj file automatically.

  1. Navigate to AwesomeApp/android folder
  2. Update Gradle running: ./gradlew wrapper --gradle-version 7.3.3 --distribution-type=all
  3. Open the AwesomeApp/android/settings.gradle file and add the following lines:
    apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
    include ':app'
    + includeBuild('../node_modules/react-native-gradle-plugin')
    
    + include(":ReactAndroid")
    + project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid')
    + include(":ReactAndroid:hermes-engine")
    + project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/ReactAndroid/hermes-engine')
  4. Open the AwesomeApp/android/build.gradle file and update the gradle dependency:
        //...
        repositories {
            google()
            mavenCentral()
        }
        dependencies {
    -        classpath("com.android.tools.build:gradle:4.2.2")
    +        classpath("com.android.tools.build:gradle:7.2.0")
    
    +        classpath("com.facebook.react:react-native-gradle-plugin")
    +        classpath("de.undercouch:gradle-download-task:4.1.2")
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
    
        }
    }
  5. Open the android/app/build.gradle and add the following snippet:
    project.ext.react = [
    -    enableHermes: true,  // clean and rebuild if changing
    +    enableHermes: true,  // clean and rebuild if changing
    ]
    // ...
    
    }
    
    if (enableHermes) {
    -    def hermesPath = "../../node_modules/hermes-engine/android/";
    -    debugImplementation files(hermesPath + "hermes-debug.aar")
    -    releaseImplementation files(hermesPath + "hermes-release.aar")
    +    //noinspection GradleDynamicVersion
    +    implementation("com.facebook.react:hermes-engine:+") { // From node_modules
    +        exclude group:'com.facebook.fbjni'
    +    }
    } else {
    
    // ...
    
    + configurations.all {
    +     resolutionStrategy.dependencySubstitution {
    +         substitute(module("com.facebook.react:react-native"))
    +                 .using(project(":ReactAndroid"))
    +                 .because("On New Architecture we're building React Native from source")
    +         substitute(module("com.facebook.react:hermes-engine"))
    +                .using(project(":ReactAndroid:hermes-engine"))
    +                .because("On New Architecture we're building Hermes from source")
    +     }
    + }
    
    // Run this once to be able to run the application with BUCK
    // puts all compile dependencies into folder libs for BUCK to use
    task copyDownloadableDepsToLibs(type: Copy) {
  6. Open the AwesomeApp/android/app/proguard-rules.pro and update the file adding these lines:
    -keep class com.facebook.hermes.unicode.** { *; }
    -keep class com.facebook.jni.** { *; }
  7. Run ./gradlew clean
  8. Go back to the AwesomeApp folder
  9. npx react-native run-android (Don't worry if it takes some time to complete.)
  1. Open the AppDelegate.mm file
  2. Add the following imports:
    #import <reacthermes/HermesExecutorFactory.h>
    #import <React/RCTCxxBridgeDelegate.h>
    #import <React/RCTJSIExecutorRuntimeInstaller.h>
    ``
  3. Add the following @interface, right before the @implementation keyword
    @interface AppDelegate () <RCTCxxBridgeDelegate> {
    // ...
    }
    @end
  4. Add the following function at the end of the file, before the @end keyword:
    #pragma mark - RCTCxxBridgeDelegate
    
    - (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
    {
    return std::make_unique<facebook::react::HermesExecutorFactory>(facebook::react::RCTJSIExecutorRuntimeInstaller([bridge](facebook::jsi::Runtime &runtime) {
        if (!bridge) {
            return;
        }
        })
    );
    }
  5. Open the AwesomeApp/ios/Podfile and change the hermes_enabled from false to true
  6. Open the Podfile and update the pod configurations as it follows:
    use_react_native!(
        :path => config[:reactNativePath],
        # to enable hermes on iOS, change `false` to `true` and then install pods
        :hermes_enabled => true,
    +    :fabric_enabled => true,
    +    :app_path => "#{Pod::Config.instance.installation_root}/.."
    )
  7. cd ios && RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
  8. From the AwesomeApp folder, run the app: npx react-native ru-ios
  1. Open the AwesomeApp/ios/AwesomeApp/AppDelegate.mm
  2. Add the following imports:
    #import <ReactCommon/RCTTurboModuleManager.h>
    #import <React/CoreModulesPlugins.h>
    
    #import <React/RCTDataRequestHandler.h>
    #import <React/RCTHTTPRequestHandler.h>
    #import <React/RCTFileRequestHandler.h>
    #import <React/RCTNetworking.h>
    #import <React/RCTImageLoader.h>
    #import <React/RCTGIFImageDecoder.h>
    #import <React/RCTLocalAssetImageLoader.h>
  3. Add the following code in the @interface
    @interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
        // ...
        RCTTurboModuleManager *_turboModuleManager;
    }
    @end
  4. Implement the getModuleClassFromName:
    #pragma mark RCTTurboModuleManagerDelegate
    
    - (Class)getModuleClassFromName:(const char *)name
    {
    return RCTCoreModulesClassProvider(name);
    }
  5. Implement the (std::shared_ptr<facebook::react::TurboModule>) getTurboModule:(const std::string &)name jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker:
    - (std::shared_ptr<facebook::react::TurboModule>)
        getTurboModule:(const std::string &)name
             jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker {
        return nullptr;
    }
  6. Implement the (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass method:
    - (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
    {
        // Set up the default RCTImageLoader and RCTNetworking modules.
        if (moduleClass == RCTImageLoader.class) {
            return [[moduleClass alloc] initWithRedirectDelegate:nil
                loadersProvider:^NSArray<id<RCTImageURLLoader>> *(RCTModuleRegistry * moduleRegistry) {
                return @ [[RCTLocalAssetImageLoader new]];
                }
                decodersProvider:^NSArray<id<RCTImageDataDecoder>> *(RCTModuleRegistry * moduleRegistry) {
                return @ [[RCTGIFImageDecoder new]];
                }];
        } else if (moduleClass == RCTNetworking.class) {
            return [[moduleClass alloc]
                initWithHandlersProvider:^NSArray<id<RCTURLRequestHandler>> *(
                    RCTModuleRegistry *moduleRegistry) {
                return @[
                    [RCTHTTPRequestHandler new],
                    [RCTDataRequestHandler new],
                    [RCTFileRequestHandler new],
                ];
                }];
        }
        // No custom initializer here.
        return [moduleClass new];
    }
  7. Run npx react-native run-ios
  1. Open the AwesomeApp/ios/AwesomeApp/AppDelegate.mm
  2. Update the - (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *) method:
    - (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
    {
    // Add these lines to create a TurboModuleManager
    if (RCTTurboModuleEnabled()) {
        _turboModuleManager =
            [[RCTTurboModuleManager alloc] initWithBridge:bridge
                                                delegate:self
                                                jsInvoker:bridge.jsCallInvoker];
    
        // Necessary to allow NativeModules to lookup TurboModules
        [bridge setRCTTurboModuleRegistry:_turboModuleManager];
    
        if (!RCTTurboModuleEagerInitEnabled()) {
        /**
        * Instantiating DevMenu has the side-effect of registering
        * shortcuts for CMD + d, CMD + i,  and CMD + n via RCTDevMenu.
        * Therefore, when TurboModules are enabled, we must manually create this
        * NativeModule.
        */
        [_turboModuleManager moduleForName:"DevMenu"];
        }
    }
    
    // Add this line...
    __weak __typeof(self) weakSelf = self;
    
    // If you want to use the `JSCExecutorFactory`, remember to add the `#import <React/JSCExecutorFactory.h>`
    // import statement on top.
    return std::make_unique<facebook::react::HermesExecutorFactory>(
        facebook::react::RCTJSIExecutorRuntimeInstaller([weakSelf, bridge](facebook::jsi::Runtime &runtime) {
        if (!bridge) {
            return;
        }
    
        // And add these lines to install the bindings...
        __typeof(self) strongSelf = weakSelf;
        if (strongSelf) {
            facebook::react::RuntimeExecutor syncRuntimeExecutor =
                [&](std::function<void(facebook::jsi::Runtime & runtime_)> &&callback) { callback(runtime); };
            [strongSelf->_turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor];
        }
        }));
    }
  3. Run npx react-native run-ios
  1. Open the AwesomeApp/ios/AwesomeApp/AppDelegate.mm
  2. Update the (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method
        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
        {
    +       RCTEnableTurboModule(YES);
    
            RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self
                                                      launchOptions:launchOptions];
  3. Run npx react-native run-ios
  1. Open the AwesomeApp/android/app/build.gradle file and update it as it follows:
    1. Add the following additional configurations:
          defaultConfig {
              applicationId "com.awesomeapp"
              minSdkVersion rootProject.ext.minSdkVersion
              targetSdkVersion rootProject.ext.targetSdkVersion
              versionCode 1
              versionName "1.0"
      
      +        externalNativeBuild {
      +            ndkBuild {
      +                arguments "APP_PLATFORM=android-21",
      +                    "APP_STL=c++_shared",
      +                    "NDK_TOOLCHAIN_VERSION=clang",
      +                    "GENERATED_SRC_DIR=$buildDir/generated/source",
      +                    "PROJECT_BUILD_DIR=$buildDir",
      +                    "REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
      +                    "REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
      +                    "NODE_MODULES_DIR=$rootDir/../node_modules/"
      +                cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
      +                cppFlags "-std=c++17"
      +                // Make sure this target name is the same you specify inside the
      +                // src/main/jni/Android.mk file for the `LOCAL_MODULE` variable.
      +                targets "awesomeapp_appmodules"
      +            }
      +        }
          }
      
      +    externalNativeBuild {
      +        ndkBuild {
      +            path "$projectDir/src/main/jni/Android.mk"
      +        }
      +    }
    2. After the applicationVariants, before closing the android block, add the following code:
              }
          }
      +    def reactAndroidProjectDir = project(':ReactAndroid').projectDir
      +    def packageReactNdkLibs = tasks.register("packageReactNdkLibs", Copy) {
      +        dependsOn(":ReactAndroid:packageReactNdkLibsForBuck")
      +        from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
      +        into("$buildDir/react-ndk/exported")
      +    }
      +
      +    afterEvaluate {
      +        preBuild.dependsOn(packageReactNdkLibs)
      +        configureNdkBuildDebug.dependsOn(preBuild)
      +        configureNdkBuildRelease.dependsOn(preBuild)
      +    }
      +
      +    packagingOptions {
      +        pickFirst '**/libhermes.so'
      +        pickFirst '**/libjsc.so'
      +    }
      }
    3. Finally, in the dependencies block, perform this change:
      implementation fileTree(dir: "libs", include: ["*.jar"])
      //noinspection GradleDynamicVersion
      - implementation "com.facebook.react:react-native:+"  // From node_modules
      + implementation project(":ReactAndroid")  // From node_modules
      ```
  2. Create an AwesomeApp/android/app/src/main/jni/Android.mk file, with the following content:
    THIS_DIR := $(call my-dir)
    
    include $(REACT_ANDROID_DIR)/Android-prebuilt.mk
    
    # If you wish to add a custom TurboModule or Fabric component in your app you
    # will have to include the following autogenerated makefile.
    # include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
    
    # Includes the MK file for autolinked libraries
    include $(PROJECT_BUILD_DIR)/generated/rncli/src/main/jni/Android-rncli.mk
    
    include $(CLEAR_VARS)
    
    LOCAL_PATH := $(THIS_DIR)
    
    # You can customize the name of your application .so file here.
    LOCAL_MODULE := awesomeapp_appmodules
    
    LOCAL_C_INCLUDES := $(LOCAL_PATH) $(PROJECT_BUILD_DIR)/generated/rncli/src/main/jni
    LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(PROJECT_BUILD_DIR)/generated/rncli/src/main/jni/*.cpp)
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(PROJECT_BUILD_DIR)/generated/rncli/src/main/jni
    
    # If you wish to add a custom TurboModule or Fabric component in your app you
    # will have to uncomment those lines to include the generated source
    # files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni)
    #
    # LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
    # LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
    # LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
    
    # Here you should add any native library you wish to depend on.
    LOCAL_SHARED_LIBRARIES := \
    libfabricjni \
    libfbjni \
    libfolly_runtime \
    libglog \
    libjsi \
    libreact_codegen_rncore \
    libreact_debug \
    libreact_nativemodule_core \
    libreact_render_componentregistry \
    libreact_render_core \
    libreact_render_debug \
    libreact_render_graphics \
    librrc_view \
    libruntimeexecutor \
    libturbomodulejsijni \
    libyoga
    
    # Autolinked libraries
    LOCAL_SHARED_LIBRARIES += $(call import-codegen-modules)
    
    LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17
    
    include $(BUILD_SHARED_LIBRARY)
  3. From the AwesomeApp folder, run npx react-native run-android

NOTE: Make sure that the targets property in the externalNativeBuild/ndkBuild of the gradle.build file matches the LOCAL_MODULE property of the Android.mk file

  1. run this command:
    cp node_modules/react-native/template/android/app/src/main/java/com/helloworld/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java android/app/src/main/java/com/awesomeapp/MainApplicationTurboModuleManagerDelegate.java
    
    This will copy the MainApplicationTurboModuleManagerDelegate.java from the template to the proper folder
  2. Open the android/app/src/main/java/com/awesomeapp/MainApplicationTurboModuleManagerDelegate.java and update it as follow:
    - package com.helloworld.newarchitecture.modules;
    + package com.awesomeapp;
    
    import com.facebook.jni.HybridData;
    import com.facebook.react.ReactPackage;
    
    // ...
    
    @Override
    protected synchronized void maybeLoadOtherSoLibraries() {
        // Prevents issues with initializer interruptions.
        if (!sIsSoLibraryLoaded) {
    -        SoLoader.loadLibrary("helloworld_appmodules");
    +        SoLoader.loadLibrary("awesomeapp_appmodules");
            sIsSoLibraryLoaded = true;
        }
    }
    
    Note: Make sure that parameter of the SoLoader.loadLibrary function in the maybeLoadOtherSoLibraries is the same name used in the LOCAL_MODULE property of the Android.mk file.
  3. npx react-native run-android
  1. Open the AwesomeApp/android/app/src/java/main/MainApplication.java file
  2. Add the imports:
    import androidx.annotation.NonNull;
    import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
  3. After the getJSMainModuleName() method, within the ReactNativeHost construction, add the following method:
    @NonNull
    @Override
    protected ReactPackageTurboModuleManagerDelegate.Builder getReactPackageTurboModuleManagerDelegateBuilder() {
        return new MainApplicationTurboModuleManagerDelegate.Builder();
    }
  4. npx react-native run-android

Referring to this step, we now have to add a few files in the AwesomeApp/android/app/src/main/jni folder:

  • MainApplicationTurboModuleManagerDelegate.h
  • MainApplicationTurboModuleManagerDelegate.cpp
  • MainApplicationModuleProvider.h
  • MainApplicationModuleProvider.cpp
  • OnLoad.cpp
  1. Run this command from the root of your app.
    cp node_modules/react-native/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h
    cp node_modules/react-native/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp
    cp node_modules/react-native/template/android/app/src/main/jni/MainApplicationModuleProvider.h android/app/src/main/jni/MainApplicationModuleProvider.h
    cp node_modules/react-native/template/android/app/src/main/jni/MainApplicationModuleProvider.cpp android/app/src/main/jni/MainApplicationModuleProvider.cpp
    cp node_modules/react-native/template/android/app/src/main/jni/OnLoad.cpp android/app/src/main/jni/OnLoad.cpp
    
    This command will copy these 5 files from the React Native template into your app.
  2. Open the AwesomeApp/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h and update it as follows:
    // ...
    class MainApplicationTurboModuleManagerDelegate
        : public jni::HybridClass<
          MainApplicationTurboModuleManagerDelegate,
          TurboModuleManagerDelegate> {
    public:
    // Adapt it to the package you used for your Java class.
    static constexpr auto kJavaDescriptor =
    -    "Lcom/helloworld/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;";
    +    "Lcom/awesomeapp/MainApplicationTurboModuleManagerDelegate;";
  3. Open the AwesomeApp/android/app/src/main/jni/OnLoad.cpp file and update it as follow:
    #include <fbjni/fbjni.h>
    #include "MainApplicationTurboModuleManagerDelegate.h"
    
    - #include "MainComponentsRegistry.h"
    + // #include "MainComponentsRegistry.h"
    
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
        return facebook::jni::initialize(vm, [] {
            facebook::react::MainApplicationTurboModuleManagerDelegate::
                registerNatives();
    -        facebook::react::MainComponentsRegistry::registerNatives();
    +//        facebook::react::MainComponentsRegistry::registerNatives();
        });
    }
    
    Comment out Fabric-specific code, we will need it later.
  4. run npx react-native run-android
  • Open the AwesomeApp/android/app/src/main/java/com/awesomeapp/MainApplication.java file
  • Add the import for the feature flags
    import com.facebook.react.ReactPackage;
    + import com.facebook.react.config.ReactFeatureFlags;
    import com.facebook.soloader.SoLoader;
  • Modify the OnCreate file as it follows:
        @Override
        public void onCreate() {
            super.onCreate();
    +        ReactFeatureFlags.useTurboModules = true;
            SoLoader.init(this, /* native exopackage */ false);
            initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
        }
  • Run npx react-native run-android
  1. Open the AwesomeApp/ios/AwesomeApp/AppDelegate.mm file.
  2. Add the following imports:
    #import <React/RCTFabricSurfaceHostingProxyRootView.h>
    #import <React/RCTSurfacePresenter.h>
    #import <React/RCTSurfacePresenterBridgeAdapter.h>
    #import <react/config/ReactNativeConfig.h>
  3. Add the following properties in the AppDelegate interface:
    @interface AppDelegate () <RCTCxxBridgeDelegate,
                           RCTTurboModuleManagerDelegate> {
    
    +   RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
    +   std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
    +   facebook::react::ContextContainer::Shared _contextContainer;
    @end
  4. Update the rootView property as it follows:
    RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
    - RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"AwesomeApp"
                                            initialProperties:nil];
    + _contextContainer = std::make_shared<facebook::react::ContextContainer const>();
    + _reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
    
    + _contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
    
    + _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc]
            initWithBridge:bridge
          contextContainer:_contextContainer];
    
    + bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
    
    + UIView *rootView = [[RCTFabricSurfaceHostingProxyRootView alloc] initWithBridge:bridge
                                                                           moduleName:@"AwesomeApp"
                                                 initialProperties:@{}];
  5. From AwesomeApp, run npx react-native run-ios
  1. Open AwesomeApp/android/app/src/main/java/com/awesomeapp/MainApplication.java
  2. Add the imports:
    import androidx.annotation.Nullable;
    import com.facebook.react.bridge.JSIModulePackage;
    import com.facebook.react.bridge.JSIModuleProvider;
    import com.facebook.react.bridge.JSIModuleSpec;
    import com.facebook.react.bridge.JSIModuleType;
    import com.facebook.react.bridge.JavaScriptContextHolder;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.bridge.UIManager;
    import com.facebook.react.fabric.ComponentFactory;
    import com.facebook.react.fabric.CoreComponentsRegistry;
    import com.facebook.react.fabric.FabricJSIModuleProvider;
    import com.facebook.react.fabric.EmptyReactNativeConfig;
    import com.facebook.react.uimanager.ViewManagerRegistry;
    import java.util.ArrayList;
  3. Update the ReactNativeHost with this new method:
    @Nullable
    @Override
    protected JSIModulePackage getJSIModulePackage() {
        return new JSIModulePackage() {
            @Override
            public List<JSIModuleSpec> getJSIModules(
                final ReactApplicationContext reactApplicationContext,
                final JavaScriptContextHolder jsContext) {
                    final List<JSIModuleSpec> specs = new ArrayList<>();
                    specs.add(new JSIModuleSpec() {
                        @Override
                        public JSIModuleType getJSIModuleType() {
                        return JSIModuleType.UIManager;
                        }
    
                        @Override
                        public JSIModuleProvider<UIManager> getJSIModuleProvider() {
                        final ComponentFactory componentFactory = new ComponentFactory();
                        CoreComponentsRegistry.register(componentFactory);
                        final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
    
                        ViewManagerRegistry viewManagerRegistry =
                            new ViewManagerRegistry(
                                reactInstanceManager.getOrCreateViewManagers(
                                    reactApplicationContext));
    
                        return new FabricJSIModuleProvider(
                            reactApplicationContext,
                            componentFactory,
                            new EmptyReactNativeConfig(),
                            viewManagerRegistry);
                        }
                    });
                    return specs;
            }
        };
    }
  4. Run npx react-native run-android
  1. Run the following command to copy the MainComponentsRegistry files from the template to the app:
    cp node_modules/react-native/template/android/app/src/main/jni/MainComponentsRegistry.h android/app/src/main/jni/MainComponentsRegistry.h
    cp node_modules/react-native/template/android/app/src/main/jni/MainComponentsRegistry.cpp android/app/src/main/jni/MainComponentsRegistry.cpp
    cp node_modules/react-native/template/android/app/src/main/java/com/helloworld/newarchitecture/components/MainComponentsRegistry.java android/app/src/main/java/com/awesomeapp/MainComponentsRegistry.java
  2. Open the android/app/src/main/java/com/awesomeapp/MainComponentsRegistry.java file and update the package:
    - package com.helloworld.newarchitecture.components;
    + package com.awesomeapp;
    
    import com.facebook.jni.HybridData;
  3. Open the android/app/src/main/jni/MainComponentRegistry.h and update it as it follows:
    class MainComponentsRegistry
        : public facebook::jni::HybridClass<MainComponentsRegistry> {
    public:
    // Adapt it to the package you used for your Java class.
    constexpr static auto kJavaDescriptor =
    -    "Lcom/helloworld/newarchitecture/components/MainComponentsRegistry;";
    +    "Lcom/awesomeapp/MainComponentsRegistry;";
    
    static void registerNatives();
  4. Open the AwesomeApp/android/app/src/main/jni/OnLoad.cpp
  5. Update it removing the comments on the commented lines, actually enabling them:
    #include <fbjni/fbjni.h>
    #include "MainApplicationTurboModuleManagerDelegate.h"
    -// #include "MainComponentsRegistry.h"
    + #include "MainComponentsRegistry.h"
    
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
    return facebook::jni::initialize(vm, [] {
        facebook::react::MainApplicationTurboModuleManagerDelegate::
            registerNatives();
    -//    facebook::react::MainComponentsRegistry::registerNatives();
    +    facebook::react::MainComponentsRegistry::registerNatives();
    });
    }
  6. Open the AwesomeApp/android/app/src/main/java/com/awesomeapp/MainApplication.java and add the following line:
    @Override
    public JSIModuleProvider<UIManager> getJSIModuleProvider() {
      final ComponentFactory componentFactory = new ComponentFactory();
      CoreComponentsRegistry.register(componentFactory);
    +  MainComponentsRegistry.register(componentFactory);
      final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
  7. Run npx react-native run-android
  1. Open AwesomeApp/android/app/src/main/java/com/awesomeapp/MainActivity.java
  2. Add the following imports:
    import com.facebook.react.ReactActivityDelegate;
    import com.facebook.react.ReactRootView;
  3. Add the MainActivityDelegate within the MainActivity class:
    public class MainActivity extends ReactActivity {
    
    +    // Add the Activity Delegate, if you don't have one already.
    +    public static class MainActivityDelegate extends ReactActivityDelegate {
    
    +        public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
    +            super(activity, mainComponentName);
    +        }
    
    +        @Override
    +        protected ReactRootView createRootView() {
    +        ReactRootView reactRootView = new ReactRootView(getContext());
    +        reactRootView.setIsFabric(true);
    +        return reactRootView;
    +        }
    +    }
    
    +    // Make sure to override the `createReactActivityDelegate()` method.
    +    @Override
    +    protected ReactActivityDelegate createReactActivityDelegate() {
    +        return new MainActivityDelegate(this, getMainComponentName());
    +    }
    
        /**
        * Returns the name of the main component registered from JavaScript. This is used to schedule
        * rendering of the component.
        */
        @Override
        protected String getMainComponentName() {
            return "AwesomeApp";
        }
    }
  4. Run npx react-native run-android
  1. Create a folder at the same level of AwesomeApp and call it calculator.
  2. Create a package.json file and add the following code:
    {
        "name": "calculator",
        "version": "0.0.1",
        "description": "Calculator TurboModule",
        "react-native": "src/index",
        "source": "src/index",
        "files": [
            "src",
            "android",
            "ios",
            "calculator.podspec",
            "!android/build",
            "!ios/build",
            "!**/__tests__",
            "!**/__fixtures__",
            "!**/__mocks__"
        ],
        "keywords": ["react-native", "ios", "android"],
        "repository": "https://github.com/<your_github_handle>/calculator",
        "author": "<Your Name> <your_email@your_provider.com> (https://github.com/<your_github_handle>)",
        "license": "MIT",
        "bugs": {
            "url": "https://github.com/<your_github_handle>/calculator/issues"
        },
        "homepage": "https://github.com/<your_github_handle>/claculator#readme",
        "devDependencies": {},
        "peerDependencies": {
            "react": "*",
            "react-native": "*"
        }
    }
  1. Create a new folder calculator/src
  2. Create a new file calculator/src/NativeCalculator.js with this code:
    // @flow
    import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport';
    import { TurboModuleRegistry } from 'react-native';
    
    export interface Spec extends TurboModule {
        // your module methods go here, for example:
        add(a: number, b: number): Promise<number>;
    }
    export default (TurboModuleRegistry.get<Spec>(
        'RNCalculator'
    ): ?Spec);
  1. Open the calculator/package.json file
  2. Add the following code at the end of the file:
    ,
    "codegenConfig": {
        "libraries": [
            {
                "name": "RNCalculatorSpec",
                "type": "modules",
                "jsSrcsDir": "src"
            }
        ]
    }
  1. Create a calculator/calculator.podspec file with this code:
    require "json"
    
    package = JSON.parse(File.read(File.join(__dir__, "package.json")))
    
    folly_version = '2021.07.22.00'
    folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
    
    Pod::Spec.new do |s|
        s.name            = "calculator"
        s.version         = package["version"]
        s.summary         = package["description"]
        s.description     = package["description"]
        s.homepage        = package["homepage"]
        s.license         = package["license"]
        s.platforms       = { :ios => "11.0" }
        s.author          = package["author"]
        s.source          = { :git => package["repository"], :tag => "#{s.version}" }
    
        s.source_files    = "ios/**/*.{h,m,mm,swift}"
    
        s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
        s.pod_target_xcconfig    = {
            "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
            "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
        }
    
        s.dependency "React-Core"
        s.dependency "React-Codegen"
        s.dependency "RCT-Folly", folly_version
        s.dependency "RCTRequired"
        s.dependency "RCTTypeSafety"
        s.dependency "ReactCommon/turbomodule/core"
    end
  1. Create a calculator/ios folder
  2. Create a new file named RNCalculator.h
  3. Create a new file named RNCalculator.mm
  4. Open the RNCalculator.h file and fill it with this code:
    #import <RNCalculatorSpec/RNCalculatorSpec.h>
    
    @interface RNCalculator : NSObject <NativeCalculatorSpec>
    
    @end
  5. Replcase the RNCalculator.mm with the following code:
    #import "RNCalculator.h"
    #import "RNCalculatorSpec.h"
    
    @implementation RNCalculator
    
    RCT_EXPORT_MODULE()
    
    - (void)add:(double)a b:(double)b resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
        NSNumber *result = [[NSNumber alloc] initWithInteger:a+b];
        resolve(result);
    }
    
    - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
        (const facebook::react::ObjCTurboModule::InitParams &)params
    {
        return std::make_shared<facebook::react::NativeCalculatorSpecJSI>(params);
    }
    @end
  1. In the calculator/android folder, create an build.gradle file and add the following code:
    buildscript {
        ext.safeExtGet = {prop, fallback ->
            rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
        }
        repositories {
            google()
            gradlePluginPortal()
        }
        dependencies {
            classpath("com.android.tools.build:gradle:7.1.1")
        }
    }
    
    apply plugin: 'com.android.library'
    apply plugin: 'com.facebook.react'
    
    android {
        compileSdkVersion safeExtGet('compileSdkVersion', 31)
    
        defaultConfig {
            minSdkVersion safeExtGet('minSdkVersion', 21)
            targetSdkVersion safeExtGet('targetSdkVersion', 31)
        }
    }
    
    repositories {
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$projectDir/../node_modules/react-native/android"
        }
        mavenCentral()
        google()
    }
    
    dependencies {
        implementation(project(":ReactAndroid"))
    }
    
    react {
        jsRootDir = file("../src/")
        libraryName = "calculator"
        codegenJavaPackageName = "com.calculator"
    }
  1. Create the following file calculator/android/src/main/AndroidManifest.xml:
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.calculator">
    </manifest>
  2. Create the CalculatorModule file at the path calculator/android/src/main/java/com/calculator/CalculatorModule.java:
    package com.calculator;
    
    import com.facebook.react.bridge.NativeModule;
    import com.facebook.react.bridge.Promise;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.bridge.ReactContext;
    import com.facebook.react.bridge.ReactContextBaseJavaModule;
    import com.facebook.react.bridge.ReactMethod;
    import java.util.Map;
    import java.util.HashMap;
    
    public class CalculatorModule extends NativeCalculatorSpec {
        public static final String NAME = "RNCalculator";
    
        CalculatorModule(ReactApplicationContext context) {
            super(context);
        }
    
        @Override
        public String getName() {
            return NAME;
        }
    
        @ReactMethod
        public void add(double a, double b, Promise promise) {
            promise.resolve(a + b);
        }
    }
  3. Create the CalculatorPackage.java at calculator/android/src/main/java/com/calculator/CalculatorPackage.java:
    package com.calculator;
    
    import androidx.annotation.Nullable;
    
    import com.facebook.react.bridge.NativeModule;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.module.model.ReactModuleInfo;
    import com.facebook.react.module.model.ReactModuleInfoProvider;
    import com.facebook.react.TurboReactPackage;
    import com.facebook.react.uimanager.ViewManager;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.HashMap;
    
    public class CalculatorPackage extends TurboReactPackage {
    
        @Nullable
        @Override
        public NativeModule getModule(String name, ReactApplicationContext reactContext) {
            if (name.equals(CalculatorModule.NAME)) {
                return new CalculatorModule(reactContext);
            } else {
                return null;
            }
        }
    
        @Override
        public ReactModuleInfoProvider getReactModuleInfoProvider() {
            return () -> {
                final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
                moduleInfos.put(
                        CalculatorModule.NAME,
                        new ReactModuleInfo(
                                CalculatorModule.NAME,
                                CalculatorModule.NAME,
                                false, // canOverrideExistingModule
                                false, // needsEagerInit
                                true, // hasConstants
                                false, // isCxxModule
                                true // isTurboModule
                ));
                return moduleInfos;
            };
        }
    }
  1. Navigate to the AwesomeApp folder.
  2. Run yarn add ../calculator
  3. Run rm -rf ios/Pods ios/Podfile.lock ios/build
  4. Run cd ios && RCT_NEW_ARCH_ENABLED=1 pod install
  5. Run open AwesomeApp.xcworkspace
  6. Clean the project with cmd + shift + k (This step is required to clean the cache from previous builds)
  7. Run cd .. && npx react-native run-ios && npx react-native run-android
  8. Open the AwesomeApp/App.js file and replace the content with:
    /**
     * Sample React Native App
    * https://github.com/facebook/react-native
    *
    * @format
    * @flow strict-local
    */
    
    import React from 'react';
    import {useState} from "react";
    import type {Node} from 'react';
    import {
    SafeAreaView,
    StatusBar,
    Text,
    Button,
    View,
    } from 'react-native';
    import Calculator from 'calculator/src/NativeCalculator';
    
    const App: () => Node = () => {
    
    const [result, setResult] = useState<number | null>(null);
    
    async function onPress() {
        const newResult = await Calculator?.add(3,7);
        setResult(newResult ?? null);
    }
    return (
        <SafeAreaView>
        <StatusBar barStyle={'dark-content'} />
        <Text style={{ "margin":20 }}>3+7={result ?? "??"}</Text>
        <Button title="Compute" onPress={onPress} />
        </SafeAreaView>
    );
    };
    
    export default App;
  9. Press on Compute, to see the app working.
  1. Create a folder at the same level of AwesomeApp and call it centered-text.
  2. Create a package.json file and add the following code:
    {
        "name": "centered-text",
        "version": "0.0.1",
        "description": "Centered Text Fabric Component",
        "react-native": "src/index",
        "source": "src/index",
        "files": [
            "src",
            "android",
            "ios",
            "centered-text.podspec",
            "!android/build",
            "!ios/build",
            "!**/__tests__",
            "!**/__fixtures__",
            "!**/__mocks__"
        ],
        "keywords": ["react-native", "ios", "android"],
        "repository": "https://github.com/<your_github_handle>/centered-text",
        "author": "<Your Name> <your_email@your_provider.com> (https://github.com/<your_github_handle>)",
        "license": "MIT",
        "bugs": {
            "url": "https://github.com/<your_github_handle>/centered-text/issues"
        },
        "homepage": "https://github.com/<your_github_handle>/centered-text#readme",
        "devDependencies": {},
        "peerDependencies": {
            "react": "*",
            "react-native": "*"
        }
    }
  1. Create a new folder centered-text/src
  2. Create a new file centered-text/src/CenteredTextNativeComponent.js with this code:
    // @flow strict-local
    import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes';
    import type {HostComponent} from 'react-native';
    import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
    type NativeProps = $ReadOnly<{|
    ...ViewProps,
    text: ?string,
    // add other props here
    |}>;
    export default (codegenNativeComponent<NativeProps>(
    'RNCenteredText',
    ): HostComponent<NativeProps>);
  1. Open the centered-text/package.json file
  2. Add the following code at the end of the file:
    ,
    "codegenConfig": {
        "libraries": [
            {
            "name": "RNCenteredTextSpec",
            "type": "components",
            "jsSrcsDir": "src"
            }
        ]
    }
  1. Create a centered-text/centered-text.podspec file with this code:
    require "json"
    
    package = JSON.parse(File.read(File.join(__dir__, "package.json")))
    
    folly_version = '2021.07.22.00'
    folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
    
    Pod::Spec.new do |s|
        s.name            = "centered-text"
        s.version         = package["version"]
        s.summary         = package["description"]
        s.description     = package["description"]
        s.homepage        = package["homepage"]
        s.license         = package["license"]
        s.platforms       = { :ios => "11.0" }
        s.author          = package["author"]
        s.source          = { :git => package["repository"], :tag => "#{s.version}" }
        s.source_files    = "ios/**/*.{h,m,mm,swift}"
        s.dependency "React-Core"
        s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
        s.pod_target_xcconfig    = {
            "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
            "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
            "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
        }
        s.dependency "React-RCTFabric"
        s.dependency "React-Codegen"
        s.dependency "RCT-Folly", folly_version
        s.dependency "RCTRequired"
        s.dependency "RCTTypeSafety"
        s.dependency "ReactCommon/turbomodule/core"
    end
  1. Create a centered-text/ios folder
  2. Create a RNCenteredTextManager.mm file with this code:
    #import <React/RCTLog.h>
    #import <React/RCTUIManager.h>
    #import <React/RCTViewManager.h>
    
    @interface RNCenteredTextManager : RCTViewManager
    @end
    
    @implementation RNCenteredTextManager
    
    RCT_EXPORT_MODULE(RNCenteredText)
    
    RCT_EXPORT_VIEW_PROPERTY(text, NSString)
    @end
  3. Create a RNCenteredText.h file with this code:
    #import <React/RCTViewComponentView.h>
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface RNCenteredText : RCTViewComponentView
    @end
    
    NS_ASSUME_NONNULL_END
  4. Create a RNCenteredText.mm file with this code:
    #import "RNCenteredText.h"
    #import <react/renderer/components/RNCenteredTextSpec/ComponentDescriptors.h>
    #import <react/renderer/components/RNCenteredTextSpec/EventEmitters.h>
    #import <react/renderer/components/RNCenteredTextSpec/Props.h>
    #import <react/renderer/components/RNCenteredTextSpec/RCTComponentViewHelpers.h>
    #import "RCTFabricComponentsPlugins.h"
    
    using namespace facebook::react;
    
    @interface RNCenteredText () <RCTRNCenteredTextViewProtocol>
    @end
    
    @implementation RNCenteredText {
        UIView *_view;
        UILabel *_label;
    }
    
    + (ComponentDescriptorProvider)componentDescriptorProvider
    {
    return concreteComponentDescriptorProvider<RNCenteredTextComponentDescriptor>();
    }
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
    if (self = [super initWithFrame:frame]) {
        static const auto defaultProps = std::make_shared<const RNCenteredTextProps>();
        _props = defaultProps;
    
        _view = [[UIView alloc] init];
        _view.backgroundColor = [UIColor redColor];
    
        _label = [[UILabel alloc] init];
        _label.text = @"Initial value";
        [_view addSubview:_label];
    
        _label.translatesAutoresizingMaskIntoConstraints = false;
        [NSLayoutConstraint activateConstraints:@[
            [_label.leadingAnchor constraintEqualToAnchor:_view.leadingAnchor],
            [_label.topAnchor constraintEqualToAnchor:_view.topAnchor],
            [_label.trailingAnchor constraintEqualToAnchor:_view.trailingAnchor],
            [_label.bottomAnchor constraintEqualToAnchor:_view.bottomAnchor],
        ]];
        _label.textAlignment = NSTextAlignmentCenter;
        self.contentView = _view;
    }
    return self;
    }
    
    - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
    {
    const auto &oldViewProps = *std::static_pointer_cast<RNCenteredTextProps const>(_props);
    const auto &newViewProps = *std::static_pointer_cast<RNCenteredTextProps const>(props);
    
    if (oldViewProps.text != newViewProps.text) {
        _label.text = [[NSString alloc] initWithCString:newViewProps.text.c_str() encoding:NSASCIIStringEncoding];
    }
    
    [super updateProps:props oldProps:oldProps];
    }
    @end
    
    Class<RCTComponentViewProtocol> RNCenteredTextCls(void)
    {
    return RNCenteredText.class;
    }
  1. In the centered-text folder, create an android folder
  2. Create an build.gradle file and add the following code:
    buildscript {
        ext.safeExtGet = {prop, fallback ->
            rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
        }
        repositories {
            google()
            gradlePluginPortal()
        }
        dependencies {
            classpath("com.android.tools.build:gradle:7.2.0")
        }
    }
    
    apply plugin: 'com.android.library'
    apply plugin: 'com.facebook.react'
    
    android {
        compileSdkVersion safeExtGet('compileSdkVersion', 31)
    
        defaultConfig {
            minSdkVersion safeExtGet('minSdkVersion', 21)
            targetSdkVersion safeExtGet('targetSdkVersion', 31)
        }
    }
    
    repositories {
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$projectDir/../node_modules/react-native/android"
        }
        mavenCentral()
        google()
    }
    
    dependencies {
        implementation(project(":ReactAndroid"))
    }
    
    react {
        jsRootDir = file("../src/")
        libraryName = "centeredtext"
        codegenJavaPackageName = "com.centeredtext"
    }
  1. Create an AndroidManifest.xml file in centered-text/src/main with the following content:
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.centeredtext">
    </manifest>
  2. Create a new file centered-text/android/src/main/java/com/centeredtext/CenteredText.java:
    package com.centeredtext;
    
    import androidx.annotation.Nullable;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.graphics.Color;
    import android.widget.TextView;
    import android.view.Gravity;
    
    public class CenteredText extends TextView {
        public CenteredText(Context context) {
            super(context);
            this.configureComponent();
        }
        public CenteredText(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            this.configureComponent();
        }
        public CenteredText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.configureComponent();
        }
        private void configureComponent() {
            this.setBackgroundColor(Color.RED);
            this.setGravity(Gravity.CENTER_HORIZONTAL);
        }
    }
  3. Create a new file centered-text/android/src/main/java/com/centeredtext/CenteredTextManager.java:
    package com.centeredtext;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import com.facebook.react.bridge.ReadableArray;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.module.annotations.ReactModule;
    import com.facebook.react.uimanager.SimpleViewManager;
    import com.facebook.react.uimanager.ThemedReactContext;
    import com.facebook.react.uimanager.ViewManagerDelegate;
    import com.facebook.react.uimanager.annotations.ReactProp;
    import com.facebook.react.viewmanagers.RNCenteredTextManagerInterface;
    import com.facebook.react.viewmanagers.RNCenteredTextManagerDelegate;
    
    @ReactModule(name = CenteredTextManager.NAME)
    public class CenteredTextManager extends SimpleViewManager<CenteredText>
            implements RNCenteredTextManagerInterface<CenteredText> {
        private final ViewManagerDelegate<CenteredText> mDelegate;
        static final String NAME = "RNCenteredText";
        public CenteredTextManager(ReactApplicationContext context) {
            mDelegate = new RNCenteredTextManagerDelegate<>(this);
        }
        @Nullable
        @Override
        protected ViewManagerDelegate<CenteredText> getDelegate() {
            return mDelegate;
        }
        @NonNull
        @Override
        public String getName() {
            return CenteredTextManager.NAME;
        }
        @NonNull
        @Override
        protected CenteredText createViewInstance(@NonNull ThemedReactContext context) {
            return new CenteredText(context);
        }
        @Override
        @ReactProp(name = "text")
        public void setText(CenteredText view, @Nullable String text) {
            view.setText(text);
        }
    }
  4. Open the centered-text/android/src/main/java/com/centeredtext/CenteredTextPackage.java and add the following code:
    package com.centeredtext;
    
    import com.facebook.react.ReactPackage;
    import com.facebook.react.bridge.NativeModule;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.uimanager.ViewManager;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class CenteredTextPackage implements ReactPackage {
        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            List<ViewManager> viewManagers = new ArrayList<>();
            viewManagers.add(new CenteredTextManager(reactContext));
            return viewManagers;
        }
        @Override
        public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
            return Collections.emptyList();
        }
    }
  1. Navigate to the AwesomeApp folder.
  2. Run yarn add ../centered-text
  3. Run rm -rf ios/Pods ios/Podfile.lock ios/build
  4. Open the Podfile and add the following line:
    require_relative '../node_modules/react-native/scripts/react_native_pods'
    require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
    
    platform :ios, '12.4'
    + install! 'cocoapods', :deterministic_uuids => false
  5. Run cd ios && RCT_NEW_ARCH_ENABLED=1 pod install
  6. Run open AwesomeApp.xcworkspace
  7. Clean the project with cmd + shift + k (This step is required to clean the cache from previous builds)
  8. Run cd .. && npx react-native run-ios
  9. Open the AwesomeApp/android/app/src/main/jni/OnLoad.cpp
  10. Run npx react-native run-android
  11. Update it removing the comments on the commented lines, actually enabling them:
    #include <fbjni/fbjni.h>
    #include "MainApplicationTurboModuleManagerDelegate.h"
    -// #include "MainComponentsRegistry.h"
    + #include "MainComponentsRegistry.h"
    
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
    return facebook::jni::initialize(vm, [] {
        facebook::react::MainApplicationTurboModuleManagerDelegate::
            registerNatives();
    -//    facebook::react::MainComponentsRegistry::registerNatives();
    +    facebook::react::MainComponentsRegistry::registerNatives();
    });
    }
  12. Open the AwesomeApp/App.js file and replace the content with:
    } from 'react-native';
    import Calculator from 'calculator/src/NativeCalculator';
    + import CenteredText from 'centered-text/src/CenteredTextNativeComponent';
    
    // ...
    
        <Text style={{ "margin":20 }}>3+7={result ?? "??"}</Text>
        <Button title="Compute" onPress={onPress} />
    +    <CenteredText text="Hello World" style={{width:"100%", height:"30"}} />
        </SafeAreaView>
    );

About

A collection of sample React Native Apps that will show you how to use the New Architecture (Fabric & TurboModules) step-by-step.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •