Basic example of Native Modules and Native UI Components.
iOS docs
-
Subclass
RCTViewManagerand return your native view.// CustomViewManager.swift @objc (RCTCustomViewManager) class RCTCustomViewManager: RCTViewManager { override func view() -> UIView! { return CustomView() } }
-
Create an implementation file to define the
RCTViewManager.// CustomViewManager.m @interface RCT_EXTERN_MODULE(RCTCustomViewManager, RCTViewManager) @end
-
Add Properties
Declare in your View subclass
// CustomView.swift @objc var myProperty: String? { didSet { //do something with the value } }
also, in your implementation file
// CustomViewManager.m @interface RCT_EXTERN_MODULE(RCTCustomViewManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(myProperty, NSString) @end
-
Add Events
Declare it in your View subclass
// CustomView.swift @objc var onMyEvent: RCTBubblingEventBlock?
and create a convenient method to call it
// CustomView.swift @objc func myEvent() { guard let onMyEvent = onMyEvent else { return } let data = ["key":"value"] //data you want to send to JS onMyEvent(data) }
Add the event declaration in your implementation file.
// CustomViewManager.m @interface RCT_EXTERN_MODULE(RCTCustomViewManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(myProperty, NSString) RCT_EXPORT_VIEW_PROPERTY(onMyEvent, RCTBubblingEventBlock) @end
Android docs
-
Subclass
ViewManagerand return your native view.// CustomViewManager.java public class RCTCustomViewManager extends SimpleViewManager<CustomView> public static final String REACT_CLASS = "RCTCustomView"; @Override public String getName() { return REACT_CLASS; } @Override public CustomView createViewInstance(ThemedReactContext context) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); CustomView view = (CustomView)inflater.inflate(R.layout.custom_view, null); return view; } }
-
Register the ViewManager
Create a subclass of
ReactPackage// CustomViewReactPackage.java public class CustomViewReactPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Arrays.<ViewManager>asList( new CustomViewManager() ); } }
and register it in your
MainApplicationfile@Override // MainApplication.java protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new CustomViewReactPackage() ); }
-
Add Properties
Declare in your
CustomViewManager.java// CustomViewManager.java @ReactProp(name = "myProperty") public void setMyProperty(CustomView view, String value) { //do something with the value }
-
Add Events
Create a method in your View subclass
// CustomView.java public void performMyEvent() { WritableMap event = Arguments.createMap(); event.putString("key", "value"); //data you want to send to JS ReactContext reactContext = (ReactContext)getContext(); reactContext.getJSModule(RCTEventEmitter.class).receiveEvent( getId(), "myEvent", event); }
and in your
CustomViewManager// CustomViewManager.java public Map getExportedCustomBubblingEventTypeConstants() { Builder events = MapBuilder.builder(); Map onMyEvent = MapBuilder.of("phasedRegistrationNames",MapBuilder.of("bubbled", "onMyEvent")); events.put("myEvent", onMyEvent); return events.build(); }
-
Create a wrapper for our native component
// CustomView.js type Props = { myProperty: string, onMyEvent: Function }; class CustomView extends Component<Props> { _onMyEvent = (event) => { if (!this.props.onMyEvent) { return; } this.props.onMyEvent(event.nativeEvent); } render() { return <RCTCustomView {...this.props} onMyEvent={this._onMyEvent} />; } } CustomView.propTypes = { myProperty: PropTypes.string, onMyEvent: PropTypes.func }; var RCTCustomView = requireNativeComponent('RCTCustomView', CustomView, { nativeOnly: { testID: true, accessibilityComponentType: true, renderToHardwareTextureAndroid: true, accessibilityLabel: true, accessibilityLiveRegion: true, importantForAccessibility: true, onLayout: true, nativeID: true } }); module.exports = CustomView;
-
And to use it
// MainView.js export default class MainView extends Component { onMyEvent = (data: Object) => { // do something with the data } render() { return ( <View style={{ flex: 1 }}> <CustomView style={{ flex: 1 }} myProperty="some value" onMyEvent ={this. onMyEvent} /> </View> ); } }
iOS docs
-
Create a class that implements
RCTBridgeModule// CustomManager.swift @objc (RCTCustomManager) class RCTCustomManager: NSObject, RCTBridgeModule { static func moduleName() -> String! { return "RCTCustomManager" } @objc func show(_ title:String, msg:String) { //do something } }
Android docs
-
Create a class that extends
ReactContextBaseJavaModule// CustomManager.java public class CustomManager extends ReactContextBaseJavaModule { public CustomManager(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "RCTCustomManager"; } @ReactMethod public void show(String title, String msg) { //do something } }
-
Register the module
Create a subclass of
ReactPackage// CustomViewReactPackage.java public class CustomViewReactPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new CustomManager(reactContext)); return modules; } }
and register it in your
MainApplicationfile// MainApplication.java @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new CustomViewReactPackage() ); }
-
Create the Module
// manager.js import { NativeModules } from 'react-native'; module.exports = NativeModules.CustomManager;
-
and to use it
CustomManager.show('a title', 'a message');

