Add support for setNativeProps to Fabric (#25737)
Add support for `setNativeProps` in Fabric to make migration to the new architecture easier. The React Native part of this has already landed in the core and iOS in https://github.com/facebook/react-native/commit/1d3fa40c59b234f21f516db85c322ec0ed0311e0. It is still recommended to move away from `setNativeProps` because the API will not work with future features.
Samuel Susla committed
Dec 9, 2022 at 14:43 UTC
b14d7fa4b88dad5f0017d084e462952c700aa2ad
4 files changed
+18
-16
packages/react-native-renderer/src/ReactFabricHostConfig.js
+11
-5
@@ -18,7 +18,10 @@ import type {
18
TouchedViewDataAtPoint,
19
} from './ReactNativeTypes';
20
21
-import {mountSafeCallback_NOT_REALLY_SAFE} from './NativeMethodsMixinUtils';
21
+import {
22
+ mountSafeCallback_NOT_REALLY_SAFE,
23
+ warnForStyleProps,
24
+} from './NativeMethodsMixinUtils';
25
import {create, diff} from './ReactNativeAttributePayload';
26
27
import {dispatchEvent} from './ReactFabricEventEmitter';
@@ -52,6 +55,7 @@ const {
55
unstable_DefaultEventPriority: FabricDefaultPriority,
56
unstable_DiscreteEventPriority: FabricDiscretePriority,
57
unstable_getCurrentEventPriority: fabricGetCurrentEventPriority,
58
+ setNativeProps,
59
} = nativeFabricUIManager;
60
61
const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
@@ -208,12 +212,14 @@ class ReactFabricHostComponent {
212
213
setNativeProps(nativeProps: Object) {
214
if (__DEV__) {
211
- console.error(
212
- 'Warning: setNativeProps is not currently supported in Fabric',
213
- );
215
+ warnForStyleProps(nativeProps, this.viewConfig.validAttributes);
216
}
217
+ const updatePayload = create(nativeProps, this.viewConfig.validAttributes);
218
216
- return;
219
+ const {stateNode} = this._internalInstanceHandle;
220
+ if (stateNode != null && updatePayload != null) {
221
+ setNativeProps(stateNode.node, updatePayload);
222
+ }
223
}
224
225
// This API (addEventListener, removeEventListener) attempts to adhere to the
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager.js
+2
@@ -117,6 +117,8 @@ const RCTFabricUIManager = {
117
118
dispatchCommand: jest.fn(),
119
120
+ setNativeProps: jest.fn(),
121
+
122
sendAccessibilityEvent: jest.fn(),
123
124
registerEventHandler: jest.fn(function registerEventHandler(callback) {}),
packages/react-native-renderer/src/__tests__/ReactFabricHostComponent-test.internal.js
+4
-10
@@ -38,7 +38,7 @@ function mockRenderKeys(keyLists) {
38
39
const mockContainerTag = 11;
40
const MockView = createReactNativeComponentClass('RCTMockView', () => ({
41
- validAttributes: {},
41
+ validAttributes: {foo: true},
42
uiViewClassName: 'RCTMockView',
43
}));
44
@@ -200,21 +200,15 @@ describe('measureLayout', () => {
200
});
201
202
describe('setNativeProps', () => {
203
- test('setNativeProps(...) emits a warning', () => {
203
+ test('setNativeProps(...) invokes setNativeProps on Fabric UIManager', () => {
204
const {
205
UIManager,
206
} = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface');
207
208
const [[fooRef]] = mockRenderKeys([['foo']]);
209
+ fooRef.setNativeProps({foo: 'baz'});
210
210
- expect(() => {
211
- fooRef.setNativeProps({});
212
- }).toErrorDev(
213
- ['Warning: setNativeProps is not currently supported in Fabric'],
214
- {
215
- withoutStack: true,
216
- },
217
- );
211
expect(UIManager.updateView).not.toBeCalled();
212
+ expect(nativeFabricUIManager.setNativeProps).toHaveBeenCalledTimes(1);
213
});
214
});
scripts/flow/react-native-host-hooks.js
+1
-1
@@ -186,7 +186,7 @@ declare var nativeFabricUIManager: {
186
payload: Object,
187
) => void,
188
) => void,
189
-
189
+ setNativeProps: (node: Object, nativeProps: Object) => Object,
190
dispatchCommand: (node: Object, command: string, args: Array<any>) => void,
191
sendAccessibilityEvent: (node: Object, eventTypeName: string) => void,
192