maboesanman
maboesanman

Reputation: 407

how to pass a react component as a native view property

I'm trying to build a react-native application with a some native UI components and some React components. I want a native ui component which takes a react component as a property, and renders it as a subview.

I went through the normal process of making a native ui component and used RCT_EXPORT_VIEW_PROPERTY(view, RCTView) to get the view property.

PagedUIViewManager.swift:

@objc(PagedUIViewManager)
class PagedUIViewManager: RCTViewManager {
  override func view() -> UIView! {
    return PagedUIView();
  }
  override static func requiresMainQueueSetup() -> Bool {
    return true
  }
}

PagedUIView.swift:

class PagedUIView: UIView {
  @objc var view: UIView {
    didSet {
      for subview in self.subviews {
        subview.removeFromSuperview()
      }
      self.addSubview(view)
    }
  }
  override init(frame: CGRect) {
    self.view = UIView(frame: frame)
    super.init(frame: frame)
    self.addSubview(view)
  }
}

PagedUIViewManager.m:

#import "React/RCTViewManager.h"
@interface RCT_EXTERN_MODULE(PagedUIViewManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(view, RCTView)
@end

PagedUINativeView.js:

const PagedUI = requireNativeComponent("PagedUIView");
export default class PagedUIView extends React.Component {
  render() {
    return <PagedUI {...this.props}/>;
  }
}

usage:

<PagedUIView view={<ComponentToRender />} />

I expected the view to show <ComponentToRender />, but instead I get the runtime error "Invariant Violation: 435,PagedView,1,[object Object] is not usable as a native method argument".

Upvotes: 5

Views: 3080

Answers (3)

David Liu
David Liu

Reputation: 9600

From this gist, you can receive subviews through the insertReactSubview method.

For example:

On the React-Native side:

<NativeView>
    <View style={{ height: 50, width: 50, backgroundColor: 'red' }} />
</NativeView>

In your native view, override insertReactSubview:

@implementation NativeView
- (void) insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex {
  // Do what you want with the subview.
}
@end

The Android equivalent is using ViewGroupManager as your view manager and overriding the addView method.

Upvotes: 0

MJ Studio
MJ Studio

Reputation: 4621

For who want to add custom child view in RN New Architecture Fabric.

#import <React/UIView+ComponentViewProtocol.h>
...

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol>*)childComponentView
                          index:(NSInteger)index {
    // ...
}
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol>*)childComponentView
                            index:(NSInteger)index {
    // ...
}
#pragma clang diagnostic pop

Upvotes: 1

elios264
elios264

Reputation: 404

It currently no possible, the only way to pass views to native modules passing the view as children.

You can receive the view using:

@objc override func insertReactSubview(_ subview: UIView!, at atIndex: Int)

Upvotes: 1

Related Questions