Issue
I am trying to create a Fabric
component. I have got it working for the most part. The only issue I am facing is I am not able to get click listener to work for a fabric
component.
I created a spec file
import type {HostComponent, ViewProps} from 'react-native';
import type {DirectEventHandler} from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
type Event = Readonly<{
value: string;
}>;
interface NativeProps extends ViewProps {
text: string;
onClickHandler?: BubblingEventHandler<Event>; ////Event name should start with on
}
export default codegenNativeComponent<NativeProps>(
'MyButtonView',
) as HostComponent<NativeProps>;
For android
my fabric
component looks like as follows
public class MyButtonView extends androidx.appcompat.widget.AppCompatButton {
public MyButtonView(Context context) {
super(context);
configureViews();
}
private void configureViews(){
setBackgroundColor(Color.YELLOW);
setOnClickListener(view -> {
onReceiveNativeEvent();
});
}
public void onReceiveNativeEvent() {
WritableMap event = Arguments.createMap();
event.putString("message", "MyMessage");
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTModernEventEmitter.class)
.receiveEvent(getId(),getId(),"onClickHandler",true,0,event,1);
}
}
Not sure what to pass first param as int
, canCoalesceEvent
, customCoalesceKey
and category
in receiveEvent
In ViewManager
I did add following code as well
@Nullable
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
Log.i("here55","999999");
return MapBuilder.of("onClickHandler",
MapBuilder.of("registrationName", "onClickHandler")
);
}
For android
I am not getting the callback
from native
android
to js
side
I am following https://reactnative.dev/docs/native-components-android but it was for the old architecture and I think is not applicable for fabric
components
Same for iOS
https://reactnative.dev/docs/native-components-ios, the doc is not very helpful for the new architecture
For iOS
, I created the header
and objective-c++
file
Typically if we want to add property we do this
RCT_EXPORT_VIEW_PROPERTY(text, NSString)
Not sure how to do it for event handler
Solution
iOS
Assuming native spec you posted is correct (I'm not really familiar with TypeScript + Codegen duo) when you run pod install
command in your ios/
directory codegen should generate EventEmitters
cpp file (+ header) in React-Codegen
pod (you can see below how to find it in XCode)
link to the screenshot with Pods structure
You can then use these classes in your Objective-C++
code to emit the events:
if (_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::$$NAME OF YOUR EVENT EMITTER TYPE$$>(_eventEmitter)
->onEvent(facebook::react::$$NAME OF YOUR EVENT EMITTER TYPE::OnEvent{.value = $$VALUE$$});
}
See links below to see how it is done in react-native-screens
- Native component spec in
Flow
- Event emission in Obj-C++ code
- Event exposure in screen manager - I'm not quite sure if this line is necessary, haven't tested it out yet.
Android
- To trigger codegen just run native build.
- Define native event class as done here
- Take a look here for how to dispatch event
- Export your event types
Answered By - K Kafara
Answer Checked By - Willingham (JavaFixing Volunteer)