react-native icon indicating copy to clipboard operation
react-native copied to clipboard

feat(RCTAppDelegate): Implement `RCTRootViewFactory`

Open okwasniewski opened this issue 5 months ago • 9 comments

Summary:

This PR implements RCTRootViewFactory a utility class (suggested by @cipolleschi) that returns proper RCTRootView based on the current environment state (new arch/old arch/bridgeless). This class aims to preserve background compatibility by implementing a configuration class forwarding necessary class to RCTAppDelegate.

Brownfield use case

This PR leverages the RCTRootViewFactory in RCTAppDelegate for the default initialization of React Native (greenfield).

Here is an example of creating a Brownfield integration (without RCTAppDelegate) using this class (can be later added to docs):

  1. Store reference to rootViewFactory and to UIWindow

AppDelegate.h:

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property(nonatomic, strong) UIWindow* window;
@property(nonatomic, strong) RCTRootViewFactory* rootViewFactory;

@end
  1. Create an initial configuration using RCTRootViewFactoryConfiguration and initialize RCTRootViewFactory using it. Then you can use the factory to create a new RCTRootView without worrying about old arch/new arch/bridgeless.

AppDelegate.mm

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions {
  
  // Create configuration
 RCTRootViewFactoryConfiguration *configuration = [[RCTRootViewFactoryConfiguration alloc] initWithBundleURL:self.bundleURL 
                                                                                                 newArchEnabled:self.fabricEnabled
                                                                                             turboModuleEnabled:self.turboModuleEnabled
                                                                                              bridgelessEnabled:self.bridgelessEnabled];

  
  // Initialize RCTRootViewFactory
  self.rootViewFactory = [[RCTRootViewFactory alloc] initWithConfiguration:configuration];
  
  // Create main root view
  UIView *rootView = [self.rootViewFactory viewWithModuleName:@"RNTesterApp" initialProperties:@{} launchOptions:launchOptions];
  
  // Set main window as you prefer for your Brownfield integration.
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  
  // Later in the codebase you can initialize more rootView's using rootViewFactory.
  
  return YES;
}
@end

Changelog:

[INTERNAL] [ADDED] - Implement RCTRootViewFactory

Test Plan:

Check if root view is properly created on app initialization

okwasniewski avatar Jan 12 '24 15:01 okwasniewski

@cipolleschi Creating RCTRootViewFactory would be the ideal solution but I didn't want to introduce too many changes. However I'm not re-creating key components every time with this approach: self.bridge, _reactHost and bridgeAdapter are created only once on the first call (I accidentally pushed code without this change at first).

Also, I can work on implementing the RCTRootViewFactory (if you are okay with having this)

okwasniewski avatar Jan 12 '24 15:01 okwasniewski

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 17,750,514 +16
android hermes armeabi-v7a n/a --
android hermes x86 n/a --
android hermes x86_64 n/a --
android jsc arm64-v8a 21,108,987 -1
android jsc armeabi-v7a n/a --
android jsc x86 n/a --
android jsc x86_64 n/a --

Base commit: 496724fbdbc85e534572f1e12f89c4af9b88e8e6 Branch: main

analysis-bot avatar Jan 12 '24 16:01 analysis-bot

@cipolleschi I decided to jump straight into it and implement this class, I think it will make initialization of RN a lot easier also in brownfield apps.

I tried to implement everything in a backward-compatible way

okwasniewski avatar Jan 15 '24 09:01 okwasniewski

Hi, @cipolleschi would you be willing to take a look at this and let me know if you're interested in pursuing it? It may require some polish, but I'd like to know if you're open to moving forward with this idea or if I should explore alternative options for react-native-visionos.

okwasniewski avatar Jan 18 '24 15:01 okwasniewski

Thanks for your review @cipolleschi I think now it's much better the public interface is not changed except for the runtimeSchedulerEnabled, bridge and bridgeAdapter but those are properties that users shouldn't override.

I also fixed those hardcoded values

okwasniewski avatar Jan 19 '24 15:01 okwasniewski

@cipolleschi As discussed offline, I've refactored the implementation to drop the delegate pattern and now we pass a configuration object. I've also validated that this PR fixes a bug with RCTRootViewExample when running bridgeless mode. RCTRootViewFactory is now decoupled from the RCTAppDelegate (so that we can move it). I've also added a short documentation to the PR description on brownfield integration using this class (tested it out on RNTester without RCTAppDelegate). Let me know what you think 👍🏻

okwasniewski avatar Jan 24 '24 14:01 okwasniewski

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

facebook-github-bot avatar Jan 29 '24 11:01 facebook-github-bot

Hey @cipolleschi, I've rebased the PR on top of the latest changes, is there anything I can do to help you get this merged?

okwasniewski avatar Feb 14 '24 14:02 okwasniewski

Hi @okwasniewski, sorry for the delay. I was quite busy in the past couple of weeks dealing with other high priority tasks and I couldn't really spend some time on this.

I'll try to make this move forward this week. Thank you for your patience!

cipolleschi avatar Feb 19 '24 15:02 cipolleschi

@cipolleschi merged this pull request in facebook/react-native@ec928d7a669fa2624bcf7da520041f140dd0fb03.

facebook-github-bot avatar Mar 04 '24 18:03 facebook-github-bot