Skip to content

Commit

Permalink
Add example in RNTester to use events with arrays (facebook#37143)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#37143

This change add an example on how to use events with arrays in the New Architecture in RNTester.

## Changelog:
[Internal] - Add Examples on RNTester on how to send events with arrays from Native to JS

Reviewed By: cortinico

Differential Revision: D45357873

fbshipit-source-id: 812521aad070181759c0a1c76b5e8c628166229c
  • Loading branch information
cipolleschi authored and jeongshin committed May 7, 2023
1 parent 55ddb79 commit cee35f4
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
* LICENSE file in the root directory of this source tree.
*/

#import <React/RCTComponent.h>
#import <React/RCTViewComponentView.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface RNTMyNativeViewComponentView : RCTViewComponentView

@property (nonatomic, copy) RCTBubblingEventBlock onIntArrayChanged;

- (UIColor *)UIColorFromHexString:(const std::string)hexString;

@end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,44 @@ - (UIColor *)UIColorFromHexString:(const std::string)hexString

- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
const auto &oldViewProps = *std::static_pointer_cast<RNTMyNativeViewProps const>(_props);
const auto &newViewProps = *std::static_pointer_cast<RNTMyNativeViewProps const>(props);

if (oldViewProps.values != newViewProps.values) {
if (_eventEmitter) {
std::vector<int> newVector = {};
std::vector<bool> newBoolVector = {};
std::vector<Float> newFloatVector = {};
std::vector<double> newDoubleVector = {};
std::vector<RNTMyNativeViewEventEmitter::OnIntArrayChangedYesNos> newYesNoVector = {};
std::vector<std::string> newStringVector = {};
std::vector<RNTMyNativeViewEventEmitter::OnIntArrayChangedLatLons> newLatLonVector = {};
std::vector<std::vector<int>> newIntVectorVector = {};
for (auto val : newViewProps.values) {
newVector.push_back(val * 2);
newBoolVector.push_back(val % 2 ? true : false);
newFloatVector.push_back(val * 3.14);
newDoubleVector.push_back(val / 3.14);
newYesNoVector.push_back(
val % 2 ? RNTMyNativeViewEventEmitter::OnIntArrayChangedYesNos::Yep
: RNTMyNativeViewEventEmitter::OnIntArrayChangedYesNos::Nope);
newStringVector.push_back(std::to_string(val));
newLatLonVector.push_back({-1.0 * val, 2.0 * val});
newIntVectorVector.push_back({val, val, val});
}
RNTMyNativeViewEventEmitter::OnIntArrayChanged value = {
newVector,
newBoolVector,
newFloatVector,
newDoubleVector,
newYesNoVector,
newStringVector,
newLatLonVector,
newIntVectorVector};
std::static_pointer_cast<RNTMyNativeViewEventEmitter const>(_eventEmitter)->onIntArrayChanged(value);
}
}

[super updateProps:props oldProps:oldProps];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ @implementation RNTMyNativeViewManager

RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor)

RCT_EXPORT_VIEW_PROPERTY(onIntArrayChanged, RCTBubblingEventBlock)

RCT_EXPORT_VIEW_PROPERTY(values, NSArray *)

RCT_EXPORT_METHOD(callNativeMethodToChangeBackgroundColor : (nonnull NSNumber *)reactTag color : (NSString *)color)
{
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
Expand Down
17 changes: 16 additions & 1 deletion packages/rn-tester/NativeComponentExample/js/MyNativeView.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,22 @@ export default function MyNativeView(props: {}): React.Node {
return (
<View ref={containerRef} style={{flex: 1}}>
<Text style={{color: 'red'}}>Fabric View</Text>
<RNTMyNativeView ref={ref} style={{flex: 1}} opacity={opacity} />
<RNTMyNativeView
ref={ref}
style={{flex: 1}}
opacity={opacity}
values={[0, 1, 2, 3, 4]}
onIntArrayChanged={event => {
console.log(event.nativeEvent.values);
console.log(event.nativeEvent.boolValues);
console.log(event.nativeEvent.floats);
console.log(event.nativeEvent.doubles);
console.log(event.nativeEvent.yesNos);
console.log(event.nativeEvent.strings);
console.log(event.nativeEvent.latLons);
console.log(event.nativeEvent.multiArrays);
}}
/>
<Text style={{color: 'red'}}>Legacy View</Text>
<RNTMyLegacyNativeView
ref={legacyRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,32 @@ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNati
import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';
import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes';
import type {Float} from 'react-native/Libraries/Types/CodegenTypes';
import type {
Float,
Double,
Int32,
BubblingEventHandler,
} from 'react-native/Libraries/Types/CodegenTypes';
import * as React from 'react';

type Event = $ReadOnly<{
values: $ReadOnlyArray<Int32>,
boolValues: $ReadOnlyArray<boolean>,
floats: $ReadOnlyArray<Float>,
doubles: $ReadOnlyArray<Double>,
yesNos: $ReadOnlyArray<'yep' | 'nope'>,
strings: $ReadOnlyArray<string>,
latLons: $ReadOnlyArray<{|lat: Double, lon: Double|}>,
multiArrays: $ReadOnlyArray<$ReadOnlyArray<Int32>>,
}>;

type NativeProps = $ReadOnly<{|
...ViewProps,
opacity?: Float,
values: $ReadOnlyArray<Int32>,

// Events
onIntArrayChanged?: ?BubblingEventHandler<Event>,
|}>;

export type MyNativeViewType = HostComponent<NativeProps>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@
import android.view.View;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import java.util.List;

class MyNativeView extends View {

Expand Down Expand Up @@ -54,4 +59,75 @@ private void emitNativeEvent(int color) {
ReactContext reactContext = (ReactContext) getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(getId(), "onColorChanged", event);
}

void emitOnArrayChangedEvent(List<Integer> ints) {
WritableMap payload = Arguments.createMap();

WritableArray newIntArray = Arguments.createArray();
WritableArray newBoolArray = Arguments.createArray();
WritableArray newFloatArray = Arguments.createArray();
WritableArray newDoubleArray = Arguments.createArray();
WritableArray newYesNoArray = Arguments.createArray();
WritableArray newStringArray = Arguments.createArray();
WritableArray newObjectArray = Arguments.createArray();
WritableArray newArrayArray = Arguments.createArray();

for (Integer i : ints) {
newIntArray.pushInt(i * 2);
newBoolArray.pushBoolean(i % 2 == 1);
newFloatArray.pushDouble(i * 3.14);
newDoubleArray.pushDouble(i / 3.14);
newYesNoArray.pushString(i % 2 == 1 ? "yep" : "nope");
newStringArray.pushString(i.toString());

WritableMap latLon = Arguments.createMap();
latLon.putDouble("lat", -1.0 * i);
latLon.putDouble("lon", 2.0 * i);
newObjectArray.pushMap(latLon);

WritableArray innerArray = Arguments.createArray();
innerArray.pushInt(i);
innerArray.pushInt(i);
innerArray.pushInt(i);
newArrayArray.pushArray(innerArray);
}

payload.putArray("values", newIntArray);
payload.putArray("boolValues", newBoolArray);
payload.putArray("floats", newFloatArray);
payload.putArray("doubles", newDoubleArray);
payload.putArray("yesNos", newYesNoArray);
payload.putArray("strings", newStringArray);
payload.putArray("latLons", newObjectArray);
payload.putArray("multiArrays", newArrayArray);

ReactContext reactContext = (ReactContext) getContext();
int surfaceId = UIManagerHelper.getSurfaceId(reactContext);
EventDispatcher eventDispatcher =
UIManagerHelper.getEventDispatcherForReactTag(reactContext, getId());
Event event = new OnIntArrayChangedEvent(surfaceId, getId(), payload);

if (eventDispatcher != null) {
eventDispatcher.dispatchEvent(event);
}
}

class OnIntArrayChangedEvent extends Event {
private WritableMap mPayload;

public OnIntArrayChangedEvent(int surfaceId, int viewId, WritableMap payload) {
super(surfaceId, viewId);
this.mPayload = payload;
}

@Override
public String getEventName() {
return "onIntArrayChanged";
}

@Override
protected WritableMap getEventData() {
return mPayload;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
Expand All @@ -19,6 +20,10 @@
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.viewmanagers.RNTMyNativeViewManagerDelegate;
import com.facebook.react.viewmanagers.RNTMyNativeViewManagerInterface;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** View manager for {@link MyNativeView} components. */
@ReactModule(name = MyNativeViewManager.REACT_CLASS)
Expand Down Expand Up @@ -67,4 +72,29 @@ public void callNativeMethodToChangeBackgroundColor(MyNativeView view, String co
public void setOpacity(@NonNull MyNativeView view, float opacity) {
super.setOpacity(view, opacity);
}

@Override
@ReactProp(name = "values")
public void setValues(@NonNull MyNativeView view, @Nullable ReadableArray value) {
List<Integer> mValues = new ArrayList<Integer>();
for (int i = 0; i < value.size(); i++) {
mValues.add(value.getInt(i));
}
view.emitOnArrayChangedEvent(mValues);
}

@Override
public final Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
Map<String, Object> eventTypeConstants = new HashMap<String, Object>();
eventTypeConstants.putAll(
MapBuilder.<String, Object>builder()
.put(
"onIntArrayChanged",
MapBuilder.of(
"phasedRegistrationNames",
MapBuilder.of(
"bubbled", "onIntArrayChanged", "captured", "onIntArrayChangedCapture")))
.build());
return eventTypeConstants;
}
}

0 comments on commit cee35f4

Please sign in to comment.