Native View Presenting a React Native View
Does anyone know how I can have a native UIViewController present or push a React Native view, and go back and forth between the two?
If possible, I'd like to load the React Native view inside a UIViewController so I can retain my navigation bar, but use the React Native view.
I've been reading the documentation, but I have not been able to find anything that works.
I've tried a combination of this:
// RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:nil launchOptions:nil];
// RCTRootView *reactView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"My Test" initialProperties:nil];
NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
RCTRootView *reactView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"My Test"
initialProperties:nil
launchOptions:nil];
reactView.frame = self.view.frame;
[self.view addSubview:reactView];
I'm not quite sure I understand how it knows what .js React file I want it to use, or how I specify that.
To have this kind of approach working you'll at least need:
- Access to a bridge that all your
RCTRootView
s can share. If you want each root view to load a different RN component from the same bundle - they need to share the sameRCTBridge
- A
UIViewController
that its view is aRCTRootView
. You can then use this view controller as the root of a navigation controller, show it modally etc. like you've already tried to do.
Let's take a look at a very simplistic example implementation of this idea.
1. An object that holds the shared bridge
Header:
#import <Foundation/Foundation.h>
#import "RCTBridge.h"
@interface ReactBridgeManager : NSObject
@property (nonatomic, strong, readonly) RCTBridge *bridge;
-(instancetype)initWithBundleURL:(NSURL *)bundleURL launchOptions:(NSDictionary *)launchOptions;
@end
Implementation:
#import "ReactBridgeManager.h"
@interface ReactBridgeManager () <RCTBridgeDelegate>
@property (nonatomic, strong, readwrite) RCTBridge *bridge;
@property (nonatomic, strong) NSURL *bundleURL;
@end
@implementation ReactBridgeManager
- (instancetype)initWithBundleURL:(NSURL *)bundleURL launchOptions:(NSDictionary *)launchOptions
{
self = [super init];
if (self)
{
self.bundleURL = bundleURL;
self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
}
return self;
}
#pragma mark - RCTBridgeDelegate methods
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return self.bundleURL;
}
@end
2. A view controller that controls a react root view
Header
#import <UIKit/UIKit.h>
#import "RCTBridge.h"
@interface ReactViewController : UIViewController
- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString*)moduleName initialProps:(NSDictionary*)initialProps;
@end
Implementation
#import "ReactViewController.h"
#import "RCTRootView.h"
@implementation ReactViewController
- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString*)moduleName initialProps:(NSDictionary*)initialProps
{
self = [super init];
if(self)
{
self.view = [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProps];
}
return self;
}
@end
3. Usage example
You can now create instances of ReactViewController
where necessary with your react component name (this is a component that was registered in RN AppRegistry
on the JS side) and push it into your native navigation stack, show it as a modal, etc.
//when your app is initialized, create the bridge manager and hold a reference to it.
ReactBridgeManager *bridgeManager = [[ReactBridgeManager alloc] initWithBundleURL:jsCodeLocation launchOptions:launchOptions];
//create a view controller that's controlling a react root view
ReactViewController *reactViewController = [[ReactViewController alloc] initWithBridge:bridgeManager.bridge moduleName:@"MyComponent" initialProps:nil];
Taking it to the next level
You can take a look at React Native Navigation which basically uses the same concept to allow a fully native navigation solution for react-native apps. Disclaimer: I'm part of the team that develops this package :)
Comments
Post a Comment