React Native(RN for short) most of the app development process can be completed on the JS side, but some functions need to be completed on the Native side. In this case, RN and the native will inevitably need to interact, such as page hopping and data passing. This article mainly uses RN — native, native — RN — native as an example to explain how to perform basic page jump operations.

I’ve written three demos of page jumps. Here is the address:

  • RNAddNative
  • RNPushToNative
  • NativeJumpToRN

RNAddNative and RNPushToNative are both instances of RN page jumping to native. The difference is that one RNAddNative uses react-native navigation. RNPushToNative uses react navigation. After trying both navigation libraries, I prefer to use React-native navigation.

NativeJumpToRN is an example of a native page jumping to and from RN to native.

In practical development, I think it is best to separate RN pages (written by JS) from native pages (written by iOS and Android), with generic pages still implemented by RN and pages that require customization and complex functions still written by native. Try not to do RN and native component embedding. After all, it is relatively easy to write UI components. There is no need to embed an RN page in a native page as a component, or embed a native component in an RN page. Separate the two, there is a need to jump directly between the pages, so it is also easy to handle.

RN – Native

If you haven’t already created a native project, just create an RN project with a React-Native init. Android and iOS projects will do it for you. Android and iOS projects can be developed independently of RN. If you already have a native project, do your own research on how to integrate React Native into your existing native project.

Take RNPushToNative as an example to show how to jump from RN to native pages. Jumping from RN to native means creating a Module class on the native side and exporting it to the JS side by bridging it so that the JS code can call the native side.

Android

Android has three steps:

1. Define the Module class and inheritReactContextBaseJavaModule

In the Module class, override getName to declare the Module class name and create our own method for page hopping.

2. Define the Package class to implement the interfaceReactPackage

The Package class needs to implement the createNativeModules and createViewManagers methods. Initialize the Module class in createNativeModules and add it to the collection

3. Define the Application class, inherit android Application, and implement the ReactApplication interface.

Initialize the Package class in the getPackages method and add it to the collection.

The Application class is available when an RN project is created and does not need to be created. If you are integrating into an existing native project, you need to manually modify the Application class.

Module class core code:

public class OpenNativeModule extends ReactContextBaseJavaModule {

    private ReactContext mReactContext;

    public OpenNativeModule(ReactApplicationContext context) {
        super(context);
        this.mReactContext = context;
    }

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

    @ReactMethod
    public void openNativeVC() { Intent intent = new Intent(); intent.setClass(mReactContext, SettingsActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mReactContext.startActivity(intent); }}Copy the code

Package class core code:

public class TestReactPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new OpenNativeModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        returnCollections.emptyList(); }}Copy the code

Application class core code:

@Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new VectorIconsPackage(),
          new TestReactPackage()
      );
    }
Copy the code

iOS

It’s much easier on iOS than on Android. You just need to create a Module class that implements the RCTBridgeModule protocol.

OpenNativeModule. H code:

#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

@interface OpenNativeModule : NSObject<RCTBridgeModule>

@end
Copy the code

OpenNativeModule. M code:

#import "OpenNativeModule.h"
#import "AppDelegate.h"
#import "NativeViewController.h"

@implementation OpenNativeModule

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(openNativeVC) {
  dispatch_async(dispatch_get_main_queue(), ^{
    AppDelegate *delegate = (AppDelegate *)([UIApplication sharedApplication].delegate);
    UINavigationController *rootNav = delegate.navController;
    NativeViewController *nativeVC = [[NativeViewController alloc] init];
    [rootNav pushViewController:nativeVC animated:YES];
  });
}

@end
Copy the code

Finally, call RN:

import React from 'react';
import {View, Text, Button, NativeModules} from 'react-native';

var nativeModule = NativeModules.OpenNativeModule;

export default class HomeScreen extends React.Component {
  
  render() {
    return<View> <Text> </Text> <Button title={'Jump to native page'} onPress={() => {
          this.jumpToNativeView();
        }}/>
      </View>
    )
  }
  
  jumpToNativeView() { nativeModule.openNativeVC(); }}Copy the code

Native – RN – Native

See NativeJumpToRN for an example of a NativeJumpToRN and from RN to a native page. A jump from RN to native RN works the same way, except for a jump from native to RN. In this demo, I just changed the original RN page from a native page to a native page, and I embedded the original RN page in a native page.

For Android, the original launch page is MainActivity, which corresponds to an RN page. I created a LaunchActivity as the launch page and set it as the launch page in androidmanifest.xml. Add a button to the LaunchActivity and click “jump to MainActivity” to complete the jump from native page to RN. Isn’t it easy?

public class LaunchActivity extends AppCompatActivity {

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launch);

        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(LaunchActivity.this, MainActivity.class); startActivity(intent); }}); }}Copy the code

Similarly on iOS, the initialization of RN pages is done in the AppDelegate, and here we change the Window rootViewController to the native UIViewController. AppDelegate core code:

@implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary  *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; _navController = [[UINavigationController alloc] initWithRootViewController:[[HomeViewController alloc] init]]; self.window.rootViewController = _navController; [self.window makeKeyAndVisible];return YES;
}

@end
Copy the code

Create a button in HomeViewController and click button to jump to RNViewController.

@implementation HomeViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.title = @"This is a native iOS page.";
  self.view.backgroundColor = [UIColor brownColor];
  
  UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 200, 50)];
  [button setTitle:@"Click to jump to RN page" forState:UIControlStateNormal];
  [button addTarget:self action:@selector(onClickButton) forControlEvents:UIControlEventTouchUpInside];
  
  [self.view addSubview:button];
}

- (void)onClickButton {
  RNViewController *vc = [[RNViewController alloc] init];
  [self.navigationController pushViewController:vc animated:YES];
}

@end
Copy the code

The initialization of RN pages in the AppDelegate is placed in the RNViewController:

@implementation RNViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.title = @"This is an RN page.";
  
  NSURL *jsCodeLocation;
  
  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
  
  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"NativeJumpToRN"initialProperties:nil launchOptions:nil]; BackgroundColor = [[UIColor alloc] initWithRed: 1.0F green: 1.0F blue:1.0f alpha:1]; rootView.backgroundColor = [[UIColor alloc] initWithRed: 1.0F green: 1.0F blue:1.0f alpha:1]; self.view = rootView; }Copy the code

This completes the jump from native to RN.