最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Native(RCT_REMAP_METHOD) : How to export a method with a parameter and return value? - Stack Overflow

programmeradmin2浏览0评论

I'm trying to use gRPC at React Native. First, I was able to setup my gRPC module with Objective-C. Next, I made a native module for that gRPC module.

The gRPC module is quite simple.

rpc CheckEmail(EmailCheckRequest) returns (EmailCheckResponse) {}

message EmailCheckRequest {
    string email = 1;
}

message EmailCheckResponse {
    common.RetCode ret = 1; 
}

As you can see, there is one input parameter(email address) and returns a "Return Code".

I checked how to make a native module at .html and it shows how to make a module with a parameter or a module with a return value, but it does not explain how to make one with both.

Here are the examples.

Module with a parameter

RCT_EXPORT_METHOD(addEvent:(NSString *)name)
{
  RCTLogInfo(@"Pretending to create an event %@", name);
}

Module with a return value(Actually, with Promise)

RCT_REMAP_METHOD(findEvents,
                 findEventsWithResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
  NSArray *events = ...
  if (events) {
    resolve(events);
 } else {
    NSError *error = ...
    reject(@"no_events", @"There were no events", error);
  }
}

Anyway, based on this, I made my own code like this.

RCT_REMAP_METHOD(checkEmail: (NSString *)email, resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    /* ... */
}

And the react-native side javascript code is like this. var NetworkService = NativeModules.NetworkService; var ret = NetworkService.checkEmail('[email protected]');

There was no compile error, but while running the app, XCode returns this runtime error at RCT_REMAP_METHOD line "com.facebook.React.JavaScript (11):EXC_BAD_ACCESS(code=1, address=0x88)

It looks like there is something wrong with RCT_REMAP_METHOD macro, but don't know Objective-C details and don't know how to use marco.

If there is someone who knows how to use RCT_REMAP_METHOD macro to export a module with a parameter and a return value or if there is something wrong with my code, please let me know.

Additional Finding I followed the definition of RCT_REMAP_METHOD and it seems that it is okay to use RCT_EXPORT_METHOD instead, because EXPORT is redefinition of REMAP and there is an example of Promises with EXPORT, but not sure whether it is the right way to do this.

* ## Promises
 *
 * Bridge modules can also define methods that are exported to JavaScript as
 * methods that return a Promise, and are compatible with JS async functions.
 *
 * Declare the last two parameters of your native method to be a resolver block
 * and a rejecter block. The resolver block must precede the rejecter block.
 *
 * For example:
 *
 * RCT_EXPORT_METHOD(doSomethingAsync:(NSString *)aString
 *                           resolver:(RCTPromiseResolveBlock)resolve
 *                           rejecter:(RCTPromiseRejectBlock)reject
 * { ... }
 *
 * Calling `NativeModules.ModuleName.doSomethingAsync(aString)` from
 * JavaScript will return a promise that is resolved or rejected when your
 * native method implementation calls the respective block.
 *
 */

I'm trying to use gRPC at React Native. First, I was able to setup my gRPC module with Objective-C. Next, I made a native module for that gRPC module.

The gRPC module is quite simple.

rpc CheckEmail(EmailCheckRequest) returns (EmailCheckResponse) {}

message EmailCheckRequest {
    string email = 1;
}

message EmailCheckResponse {
    common.RetCode ret = 1; 
}

As you can see, there is one input parameter(email address) and returns a "Return Code".

I checked how to make a native module at https://facebook.github.io/react-native/docs/native-modules-ios.html and it shows how to make a module with a parameter or a module with a return value, but it does not explain how to make one with both.

Here are the examples.

Module with a parameter

RCT_EXPORT_METHOD(addEvent:(NSString *)name)
{
  RCTLogInfo(@"Pretending to create an event %@", name);
}

Module with a return value(Actually, with Promise)

RCT_REMAP_METHOD(findEvents,
                 findEventsWithResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
  NSArray *events = ...
  if (events) {
    resolve(events);
 } else {
    NSError *error = ...
    reject(@"no_events", @"There were no events", error);
  }
}

Anyway, based on this, I made my own code like this.

RCT_REMAP_METHOD(checkEmail: (NSString *)email, resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    /* ... */
}

And the react-native side javascript code is like this. var NetworkService = NativeModules.NetworkService; var ret = NetworkService.checkEmail('[email protected]');

There was no compile error, but while running the app, XCode returns this runtime error at RCT_REMAP_METHOD line "com.facebook.React.JavaScript (11):EXC_BAD_ACCESS(code=1, address=0x88)

It looks like there is something wrong with RCT_REMAP_METHOD macro, but don't know Objective-C details and don't know how to use marco.

If there is someone who knows how to use RCT_REMAP_METHOD macro to export a module with a parameter and a return value or if there is something wrong with my code, please let me know.

Additional Finding I followed the definition of RCT_REMAP_METHOD and it seems that it is okay to use RCT_EXPORT_METHOD instead, because EXPORT is redefinition of REMAP and there is an example of Promises with EXPORT, but not sure whether it is the right way to do this.

* ## Promises
 *
 * Bridge modules can also define methods that are exported to JavaScript as
 * methods that return a Promise, and are compatible with JS async functions.
 *
 * Declare the last two parameters of your native method to be a resolver block
 * and a rejecter block. The resolver block must precede the rejecter block.
 *
 * For example:
 *
 * RCT_EXPORT_METHOD(doSomethingAsync:(NSString *)aString
 *                           resolver:(RCTPromiseResolveBlock)resolve
 *                           rejecter:(RCTPromiseRejectBlock)reject
 * { ... }
 *
 * Calling `NativeModules.ModuleName.doSomethingAsync(aString)` from
 * JavaScript will return a promise that is resolved or rejected when your
 * native method implementation calls the respective block.
 *
 */
Share Improve this question edited Jul 16, 2017 at 0:30 Spike asked Jul 14, 2017 at 9:17 SpikeSpike 1931 gold badge2 silver badges7 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 14

RCT_EXPORT_METHOD is just to remap the js function to native function. This is useful when multiple native methods are the same up to the first colon and would have conflicting JavaScript names.

As the define RCT_REMAP_METHOD(js_name, method), the js_name means the function called from the js code, method means the native function name.

So if you want to export a method with a parameter (or more), you can do like so:

// Bridge.m

RCT_EXPORT_MODULE(Bridge)

RCT_REMAP_METHOD(findEvents,
                 type:(NSString *)type
                 params:(NSDictionary *)params
                 findEventsWithResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{ ... }

Then from the js code, call the function like this:

const Bridge = NativeModules.Bridge;

class App extends Component {
  asnyc _buttonPress() {
    try {
      let result = await Bridge.findEvents("type", {"key": "value"});
      // handle the result
    } catch(e) {
      // handle the error
    }
  }
}

Make sure the RCTPromiseResolveBlock and RCTPromiseRejectBlock are the last two parameters.

As I mentioned at the additional finding part, I was able to export a module with a parameter and a return value with RCT_EXPORT_METHOD.

RCT_EXPORT_METHOD(checkEmail: (NSString *)email 
    resolver:(RCTPromiseResolveBlock)resolve 
    rejecter:(RCTPromiseRejectBlock)reject)
{
    /* ... */
}

In this way, I was able to export "checkEmail".

Javascript : NativeModules.ModuleName.checkEmail(email);

I have no Objective-C background knowledge, so even if it works in this way, if there is something wrong with my code, please let me know. =)

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论