I am trying to integrate a Native UI component in react-native using the new architecture with fabric enabled
Here is my spec file
import type {HostComponent, ViewProps} from 'react-native';
import type {
DirectEventHandler,
BubblingEventHandler,
} from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
type Event = Readonly<{
text?: string;
}>;
interface NativeProps extends ViewProps {
text: string;
onClickHandler?: DirectEventHandler<Event>; ////Event name should start with on
}
export default codegenNativeComponent<NativeProps>(
'MyButtonView',
) as HostComponent<NativeProps>;
Then on native side I created following files
public class MyButtonViewManager extends SimpleViewManager<MyButtonView> {
public static final String NAME = "MyButtonView";
ReactApplicationContext mCallerContext;
public MyButtonViewManager(ReactApplicationContext reactContext) {
mCallerContext = reactContext;
}
@NonNull
@Override
public String getName() {
return NAME;
}
@NonNull
@Override
protected MyButtonView createViewInstance(@NonNull ThemedReactContext reactContext) {
return new MyButtonView(reactContext);
}
@ReactProp(name = "text")
public void setQrCodeText(MyButtonView view, String text) {
view.setText(text);
}
@Nullable
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.of("topOnClickHandler",
MapBuilder.of("registrationName", "onClickHandler")
);
}
}
public class MyButtonView extends androidx.appcompat.widget.AppCompatButton {
public MyButtonView(Context context) {
super(context);
configureViews();
}
private void configureViews(){
setBackgroundColor(Color.YELLOW);
setOnClickListener(view -> {
ReactContext reactContext = (ReactContext)getContext();
EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(
reactContext ,getId()
);
eventDispatcher.dispatchEvent(new MyButtonClickEvent(getId()));
});
}
}
public class MyButtonClickEvent extends Event<MyButtonClickEvent> {
public MyButtonClickEvent(int viewId) {
super(viewId);
}
@Override
public String getEventName() {
return "topOnClickHandler";
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
super.dispatch(rctEventEmitter);
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), Arguments.createMap());
}
@Nullable
@Override
protected WritableMap getEventData() {
WritableMap event = Arguments.createMap();
event.putString("message", "MyMessage");
return event;
}
}
What is the alternative to dispatch and RCTEventEmitter as both are deprecated? I was looking into RCTModernEventEmitter and it also extends the deprecated RCTEventEmitter
Also i have to change the event name from OnClickHandler to topOnClickHandler in Native Android side. It was throwing hermes error. Not sure why there should be top prefix, why can't it just be OnClickHandler.
From the react-native source code:
This [RCTModernEventEmitter] is a transitional replacement for RCTEventEmitter that works with Fabric and non-Fabric renderers. RCTEventEmitter works with Fabric as well, but there are negative perf implications and it should be avoided.
You can use this for now as a replacement that works with Fabric.
This [RCTModernEventEmitter] interface will also be deleted in the distant future and be replaced with a new interface that doesn't need the old
receiveEventmethod at all. But for the foreseeable future, this is the recommended interface to use for EventEmitters.
However, in the long run this will be removed.
There's ReactEventEmitter that might help based on your use-case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With