ReactBridge icon indicating copy to clipboard operation
ReactBridge copied to clipboard

Documentation and/or support for RCTConvert and RCT_ENUM_CONVERTER

Open andrew-schenk opened this issue 10 months ago • 4 comments

Is there an existing way to handle RCTConvert of custom values?

andrew-schenk avatar Mar 03 '25 19:03 andrew-schenk

Hi, @andrew-schenk!

Do you mean extending RCTCovert with RCT_ENUM_CONVERTER etc?

These macros are not implemented with ReactBridge but I can investigate that in the future. Now you can call RCTConvert directly for your params e.g.:

let date = RCTConvert.nsDate(secondsSinceUnixEpoch)

ikhvorost avatar Mar 03 '25 21:03 ikhvorost

@ikhvorost yes. Here is a simplified example.

If I want to call from React Native into Swift with a custom enum property, then I would set it up like so.

// javascript
NativeModule.doSomething(MyEnum.Default)
// obj-c

@implementation RCTConvert(MyEnum)
RCT_ENUM_CONVERTER(MyEnum, (@{ @"default" : @(Default),
                                   @"foobar" : @(FooBar)}),
                   Default, integerValue)
@end


RCT_EXTERN_METHOD(doSomething: (MyEnum*)enumVal 
                    resolver:(RCTPromiseResolveBlock)resolve 
                    rejecter:(RCTPromiseRejectBlock)reject)
// swift
  @objc func doSomething(_ enumVal: MyEnum, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {

with this library, we'd be cutting out the Obj-C method signature, but also we are losing the RCT_ENUM_CONVERTER.

// swift
@ReactMethod
  @objc func doSomething(_ enumVal: MyEnum, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {

// MyEnum isn't converted or handled now

There are more complex use cases where one might want to convert a complex custom object that isn't one of the default supported objects provided by RCTConvert.

andrew-schenk avatar Mar 03 '25 22:03 andrew-schenk

Thanks for the notion! I'll look at RCTConvert and find out if it's possible to extend it in swift with macros and let you know in this thread.

ikhvorost avatar Mar 04 '25 14:03 ikhvorost

Hi, @andrew-schenk!

Unfortunately it's impossible to utilize swift's enums with @objc functions for ReactBridge because of the following error:

@ReactMethod
@objc func testEnum(_ item: MyEnum) { // Error: Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C
}

So that, the only way is passing simple types such as Int or String and then converting them to your target enum.

But, RCTConvert can be extended for your objc compliant classes e.g.:

// Swift
class MyItem: NSObject {
  let id: Int
  let name: String
  
  init(id: Int, name: String) {
    self.id = id
    self.name = name
  }
}

extension RCTConvert {
  
  @objc
  class func MyItem(_ json: Dictionary<String, Any>) -> MyItem? {
    guard let id = json["id"] as? Int, let name = json["name"] as? String else {
      return nil
    }
    return TestReactNative.MyItem(id: id, name: name)
  }
}

extension Calendar {
  
  @ReactMethod
  @objc func testClass(_ item: MyItem) {
    print(item)
  }
}

// JS
Calendar.testClass({id: 200, name: 'Foo'});

ikhvorost avatar Mar 11 '25 15:03 ikhvorost