How to access native UI components' instance methods in React Native
Asked Answered
D

2

16

We can control custom native UI components' properties by exporting native properties using RCT_EXPORT_VIEW_PROPERTY.

But how to export instance methods of native UI components?

Disharmony answered 6/8, 2015 at 13:49 Comment(0)
D
16

Thanks to @alinz's suggestion.

This can be done within the custom native component's view manager.

  1. Obj-c side: In the native view manager expose a native method like this:

The key is to pass in the reactTag which is the reference to the native component.

MyCoolViewManager.m:

RCT_EXPORT_METHOD(myCoolMethod:(NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback) {
  [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
    MyCoolView *view = viewRegistry[reactTag];
    if (![view isKindOfClass:[MyCoolView class]]) {
      RCTLogMustFix(@"Invalid view returned from registry, expecting MyCoolView, got: %@", view);
    }
    // Call your native component's method here
    [view myCoolMethod];
  }];
}
  1. JS side: Add API in the react component class:

MyCoolView.js:

var React = require('react-native');
var NativeModules = require('NativeModules');
var MyCoolViewManager = NativeModules.MyCoolViewManager;
var findNodeHandle = require('findNodeHandle');

class MyCoolView extends React.Component{
    // ...
    myCoolMethod() {
        return new Promise((resolve, reject) => {
            MyCoolViewManager.myCoolMethod(
                findNodeHandle(this),
                (error, result) => {
                    if (error) {
                        reject(error);
                    } else {
                        resolve(result);
                    }
                }
            );
        });
    }
}
Disharmony answered 11/8, 2015 at 8:13 Comment(4)
This solution doesn't seem to work with new version of react native. addUIBlock is no longer callable from uiManager. Trying figure out how to resolve this.Telegu
I found a working example on github. Check it out. github.com/ProjectSeptemberInc/gl-react-native/blob/master/ios/…Gunner
FYI, I needed this for Android, and posted solution here: https://mcmap.net/q/750731/-calling-a-android-native-ui-component-method-from-react-native-js-codeSubvert
@Telegu did you figure out what to do now that addUiBlock is no longer callable?Revivalist
G
-1

I'm not an Objective C expert but a Swift developer.

I better use this way just for readability (maybe there are drawbacks in Obj-C?):

  • In Manager: store a reference to your view in an instance private property
  • it will then help to call your view's method

Obj-C side - component manager:

@implementation RNAnalogClockManager {
  RNAnalogClock* _AnalogClock;
}

RCT_EXPORT_MODULE()

- (UIView *)view
{
  // keep a reference to the view before returning it
  _AnalogClock = [[RNAnalogClock alloc] init];
  return _AnalogClock;
}

// export method and easily call view method 
RCT_EXPORT_METHOD(startRealTime) {
  [_AnalogClock startRealTime];
};

JS side remains the same

NOTE: I don't need callback in my example but it does not change the principle it is just another parameter.

Groats answered 13/8, 2016 at 8:19 Comment(3)
what happens if the start method is called before the view method? then the _AnalogClock is nil and all things are broken..Kine
Component manager is the way RN can play with native AnalogClock. View() method is called by RN to create an instance of the Native. RN can't call start timer method before it is instantiated so it can't occur.Groats
This does not seem to allow to have multiple instances of AnalogClock.Gunner

© 2022 - 2024 — McMap. All rights reserved.