Skip to content

Commit 8eee0eb

Browse files
authored
Dispatch commands to both UIManagers from both renderers (#17211)
* Dispatch commands to both UIManagers from both renderers * Merge test files
1 parent f4e974d commit 8eee0eb

File tree

3 files changed

+88
-16
lines changed

3 files changed

+88
-16
lines changed

packages/react-native-renderer/src/ReactFabric.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import {createPortal} from 'shared/ReactPortal';
2929
import {setBatchingImplementation} from 'legacy-events/ReactGenericBatching';
3030
import ReactVersion from 'shared/ReactVersion';
3131

32+
// Module provided by RN:
33+
import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
34+
3235
import NativeMethodsMixin from './NativeMethodsMixin';
3336
import ReactNativeComponent from './ReactNativeComponent';
3437
import {getClosestInstanceFromNode} from './ReactFabricComponentTree';
@@ -39,8 +42,6 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';
3942
import getComponentName from 'shared/getComponentName';
4043
import warningWithoutStack from 'shared/warningWithoutStack';
4144

42-
const {dispatchCommand: fabricDispatchCommand} = nativeFabricUIManager;
43-
4445
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
4546

4647
function findNodeHandle(componentOrHandle: any): ?number {
@@ -110,23 +111,24 @@ const ReactFabric: ReactFabricType = {
110111
findNodeHandle,
111112

112113
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) {
117115
warningWithoutStack(
118-
!invalid,
116+
handle._nativeTag != null,
119117
"dispatchCommand was called with a ref that isn't a " +
120118
'native component. Use React.forwardRef to get access to the underlying native component',
121119
);
122120
return;
123121
}
124122

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+
}
130132
},
131133

132134
render(element: React$Element<any>, containerTag: any, callback: ?Function) {

packages/react-native-renderer/src/ReactNativeRenderer.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,15 @@ const ReactNativeRenderer: ReactNativeType = {
129129
return;
130130
}
131131

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+
}
133141
},
134142

135143
render(element: React$Element<any>, containerTag: any, callback: ?Function) {

packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ let ReactNative;
1616
let UIManager;
1717
let createReactNativeComponentClass;
1818

19-
describe('ReactFabric', () => {
19+
describe('created with ReactFabric called with ReactNative', () => {
2020
beforeEach(() => {
2121
jest.resetModules();
2222
require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');
@@ -55,7 +55,7 @@ describe('ReactFabric', () => {
5555
});
5656

5757
it('dispatches commands on Fabric nodes with the RN renderer', () => {
58-
UIManager.dispatchViewManagerCommand.mockReset();
58+
nativeFabricUIManager.dispatchCommand.mockClear();
5959
const View = createReactNativeComponentClass('RCTView', () => ({
6060
validAttributes: {title: true},
6161
uiViewClassName: 'RCTView',
@@ -64,13 +64,75 @@ describe('ReactFabric', () => {
6464
let ref = React.createRef();
6565

6666
ReactFabric.render(<View title="bar" ref={ref} />, 11);
67-
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
67+
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
6868
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]);
69129
expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledTimes(1);
70130
expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledWith(
71131
expect.any(Number),
72132
'myCommand',
73133
[10, 20],
74134
);
135+
136+
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
75137
});
76138
});

0 commit comments

Comments
 (0)