@samitouri / QOS-React-2 / commits / 8eee0eb01c

Dispatch commands to both UIManagers from both renderers (#17211)

* Dispatch commands to both UIManagers from both renderers * Merge test files

Eli White committed Oct 29, 2019 at 18:16 UTC 8eee0eb01ce3ead0f51ade75fdcf062a748d57a7
3 files changed +88 -16
packages/react-native-renderer/src/ReactFabric.js
+14 -12
@@ -29,6 +29,9 @@ import {createPortal} from 'shared/ReactPortal';
29 import {setBatchingImplementation} from 'legacy-events/ReactGenericBatching';
30 import ReactVersion from 'shared/ReactVersion';
31
32 +// Module provided by RN:
33 +import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
34 +
35 import NativeMethodsMixin from './NativeMethodsMixin';
36 import ReactNativeComponent from './ReactNativeComponent';
37 import {getClosestInstanceFromNode} from './ReactFabricComponentTree';
@@ -39,8 +42,6 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';
42 import getComponentName from 'shared/getComponentName';
43 import warningWithoutStack from 'shared/warningWithoutStack';
44
42 -const {dispatchCommand: fabricDispatchCommand} = nativeFabricUIManager;
43 -
45 const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
46
47 function findNodeHandle(componentOrHandle: any): ?number {
@@ -110,23 +111,24 @@ const ReactFabric: ReactFabricType = {
111 findNodeHandle,
112
113 dispatchCommand(handle: any, command: string, args: Array<any>) {
113 - const invalid =
114 - handle._nativeTag == null || handle._internalInstanceHandle == null;
115 -
116 - if (invalid) {
114 + if (handle._nativeTag == null) {
115 warningWithoutStack(
118 - !invalid,
116 + handle._nativeTag != null,
117 "dispatchCommand was called with a ref that isn't a " +
118 'native component. Use React.forwardRef to get access to the underlying native component',
119 );
120 return;
121 }
122
125 - fabricDispatchCommand(
126 - handle._internalInstanceHandle.stateNode.node,
127 - command,
128 - args,
129 - );
123 + if (handle._internalInstanceHandle) {
124 + nativeFabricUIManager.dispatchCommand(
125 + handle._internalInstanceHandle.stateNode.node,
126 + command,
127 + args,
128 + );
129 + } else {
130 + UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
131 + }
132 },
133
134 render(element: React$Element<any>, containerTag: any, callback: ?Function) {
packages/react-native-renderer/src/ReactNativeRenderer.js
+9 -1
@@ -129,7 +129,15 @@ const ReactNativeRenderer: ReactNativeType = {
129 return;
130 }
131
132 - UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
132 + if (handle._internalInstanceHandle) {
133 + nativeFabricUIManager.dispatchCommand(
134 + handle._internalInstanceHandle.stateNode.node,
135 + command,
136 + args,
137 + );
138 + } else {
139 + UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
140 + }
141 },
142
143 render(element: React$Element<any>, containerTag: any, callback: ?Function) {
packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js
+65 -3
@@ -16,7 +16,7 @@ let ReactNative;
16 let UIManager;
17 let createReactNativeComponentClass;
18
19 -describe('ReactFabric', () => {
19 +describe('created with ReactFabric called with ReactNative', () => {
20 beforeEach(() => {
21 jest.resetModules();
22 require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');
@@ -55,7 +55,7 @@ describe('ReactFabric', () => {
55 });
56
57 it('dispatches commands on Fabric nodes with the RN renderer', () => {
58 - UIManager.dispatchViewManagerCommand.mockReset();
58 + nativeFabricUIManager.dispatchCommand.mockClear();
59 const View = createReactNativeComponentClass('RCTView', () => ({
60 validAttributes: {title: true},
61 uiViewClassName: 'RCTView',
@@ -64,13 +64,75 @@ describe('ReactFabric', () => {
64 let ref = React.createRef();
65
66 ReactFabric.render(<View title="bar" ref={ref} />, 11);
67 - expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
67 + expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
68 ReactNative.dispatchCommand(ref.current, 'myCommand', [10, 20]);
69 + expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledTimes(1);
70 + expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledWith(
71 + expect.any(Object),
72 + 'myCommand',
73 + [10, 20],
74 + );
75 + expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
76 + });
77 +});
78 +
79 +describe('created with ReactNative called with ReactFabric', () => {
80 + beforeEach(() => {
81 + jest.resetModules();
82 + require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');
83 + ReactFabric = require('react-native-renderer/fabric');
84 + jest.resetModules();
85 + UIManager = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
86 + .UIManager;
87 + jest.mock('shared/ReactFeatureFlags', () =>
88 + require('shared/forks/ReactFeatureFlags.native-oss'),
89 + );
90 + ReactNative = require('react-native-renderer');
91 +
92 + React = require('react');
93 + createReactNativeComponentClass = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
94 + .ReactNativeViewConfigRegistry.register;
95 + });
96 +
97 + it('find Paper nodes with the Fabric renderer', () => {
98 + const View = createReactNativeComponentClass('RCTView', () => ({
99 + validAttributes: {title: true},
100 + uiViewClassName: 'RCTView',
101 + }));
102 +
103 + let ref = React.createRef();
104 +
105 + class Component extends React.Component {
106 + render() {
107 + return <View title="foo" />;
108 + }
109 + }
110 +
111 + ReactNative.render(<Component ref={ref} />, 11);
112 +
113 + let handle = ReactFabric.findNodeHandle(ref.current);
114 + expect(handle).toBe(3);
115 + });
116 +
117 + it('dispatches commands on Paper nodes with the Fabric renderer', () => {
118 + UIManager.dispatchViewManagerCommand.mockReset();
119 + const View = createReactNativeComponentClass('RCTView', () => ({
120 + validAttributes: {title: true},
121 + uiViewClassName: 'RCTView',
122 + }));
123 +
124 + let ref = React.createRef();
125 +
126 + ReactNative.render(<View title="bar" ref={ref} />, 11);
127 + expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
128 + ReactFabric.dispatchCommand(ref.current, 'myCommand', [10, 20]);
129 expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledTimes(1);
130 expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledWith(
131 expect.any(Number),
132 'myCommand',
133 [10, 20],
134 );
135 +
136 + expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
137 });
138 });