Extract duplicated methods in Fabric and the legacy renderer to a shared module (#26319)
## Summary The following methods have exactly the same implementation on Fabric and the legacy renderer: * `findHostInstance_DEPRECATED` * `findNodeHandle` * `dispatchCommand` * `sendAccessibilityEvent` This just extracts those functions to a common module so they're easier to change (no need to sync changes in 2 files). ## How did you test this change? Existing tests (this is a refactor).
Rubén Norte committed
Mar 6, 2023 at 10:51 UTC
eb616a12f10a58d5dc0b5898c0a1029aef62d485
3 files changed
+179
-292
packages/react-native-renderer/src/ReactFabric.js
+6
-149
@@ -7,7 +7,6 @@
7
* @flow
8
*/
9
10
-import type {HostComponent} from './ReactNativeTypes';
10
import type {ReactPortal, ReactNodeList} from 'shared/ReactTypes';
11
import type {ElementRef, Element, ElementType} from 'react';
12
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
@@ -15,8 +14,6 @@ import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
14
import './ReactFabricInjection';
15
16
import {
18
- findHostInstance,
19
- findHostInstanceWithWarning,
17
batchedUpdates as batchedUpdatesImpl,
18
discreteUpdates,
19
createContainer,
@@ -29,12 +26,6 @@ import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal
26
import {setBatchingImplementation} from './legacy-events/ReactGenericBatching';
27
import ReactVersion from 'shared/ReactVersion';
28
32
-// Modules provided by RN:
33
-import {
34
- UIManager,
35
- legacySendAccessibilityEvent,
36
-} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
37
-
29
import {getClosestInstanceFromNode} from './ReactFabricComponentTree';
30
import {
31
getInspectorDataForViewTag,
@@ -42,146 +33,12 @@ import {
33
getInspectorDataForInstance,
34
} from './ReactNativeFiberInspector';
35
import {LegacyRoot, ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';
45
-import ReactSharedInternals from 'shared/ReactSharedInternals';
46
-import getComponentNameFromType from 'shared/getComponentNameFromType';
47
-
48
-const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
49
-
50
-function findHostInstance_DEPRECATED<TElementType: ElementType>(
51
- componentOrHandle: ?(ElementRef<TElementType> | number),
52
-): ?ElementRef<HostComponent<mixed>> {
53
- if (__DEV__) {
54
- const owner = ReactCurrentOwner.current;
55
- if (owner !== null && owner.stateNode !== null) {
56
- if (!owner.stateNode._warnedAboutRefsInRender) {
57
- console.error(
58
- '%s is accessing findNodeHandle inside its render(). ' +
59
- 'render() should be a pure function of props and state. It should ' +
60
- 'never access something that requires stale data from the previous ' +
61
- 'render, such as refs. Move this logic to componentDidMount and ' +
62
- 'componentDidUpdate instead.',
63
- getComponentNameFromType(owner.type) || 'A component',
64
- );
65
- }
66
-
67
- owner.stateNode._warnedAboutRefsInRender = true;
68
- }
69
- }
70
- if (componentOrHandle == null) {
71
- return null;
72
- }
73
- // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
74
- if (componentOrHandle._nativeTag) {
75
- // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
76
- return componentOrHandle;
77
- }
78
- // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
79
- if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
80
- // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
81
- return componentOrHandle.canonical;
82
- }
83
- let hostInstance;
84
- if (__DEV__) {
85
- hostInstance = findHostInstanceWithWarning(
86
- componentOrHandle,
87
- 'findHostInstance_DEPRECATED',
88
- );
89
- } else {
90
- hostInstance = findHostInstance(componentOrHandle);
91
- }
92
-
93
- return hostInstance;
94
-}
95
-
96
-function findNodeHandle(componentOrHandle: any): ?number {
97
- if (__DEV__) {
98
- const owner = ReactCurrentOwner.current;
99
- if (owner !== null && owner.stateNode !== null) {
100
- if (!owner.stateNode._warnedAboutRefsInRender) {
101
- console.error(
102
- '%s is accessing findNodeHandle inside its render(). ' +
103
- 'render() should be a pure function of props and state. It should ' +
104
- 'never access something that requires stale data from the previous ' +
105
- 'render, such as refs. Move this logic to componentDidMount and ' +
106
- 'componentDidUpdate instead.',
107
- getComponentNameFromType(owner.type) || 'A component',
108
- );
109
- }
110
-
111
- owner.stateNode._warnedAboutRefsInRender = true;
112
- }
113
- }
114
- if (componentOrHandle == null) {
115
- return null;
116
- }
117
- if (typeof componentOrHandle === 'number') {
118
- // Already a node handle
119
- return componentOrHandle;
120
- }
121
- if (componentOrHandle._nativeTag) {
122
- return componentOrHandle._nativeTag;
123
- }
124
- if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
125
- return componentOrHandle.canonical._nativeTag;
126
- }
127
- let hostInstance;
128
- if (__DEV__) {
129
- hostInstance = findHostInstanceWithWarning(
130
- componentOrHandle,
131
- 'findNodeHandle',
132
- );
133
- } else {
134
- hostInstance = findHostInstance(componentOrHandle);
135
- }
136
-
137
- if (hostInstance == null) {
138
- return hostInstance;
139
- }
140
-
141
- return hostInstance._nativeTag;
142
-}
143
-
144
-function dispatchCommand(handle: any, command: string, args: Array<any>) {
145
- if (handle._nativeTag == null) {
146
- if (__DEV__) {
147
- console.error(
148
- "dispatchCommand was called with a ref that isn't a " +
149
- 'native component. Use React.forwardRef to get access to the underlying native component',
150
- );
151
- }
152
- return;
153
- }
154
-
155
- if (handle._internalInstanceHandle != null) {
156
- const {stateNode} = handle._internalInstanceHandle;
157
- if (stateNode != null) {
158
- nativeFabricUIManager.dispatchCommand(stateNode.node, command, args);
159
- }
160
- } else {
161
- UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
162
- }
163
-}
164
-
165
-function sendAccessibilityEvent(handle: any, eventType: string) {
166
- if (handle._nativeTag == null) {
167
- if (__DEV__) {
168
- console.error(
169
- "sendAccessibilityEvent was called with a ref that isn't a " +
170
- 'native component. Use React.forwardRef to get access to the underlying native component',
171
- );
172
- }
173
- return;
174
- }
175
-
176
- if (handle._internalInstanceHandle != null) {
177
- const {stateNode} = handle._internalInstanceHandle;
178
- if (stateNode != null) {
179
- nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType);
180
- }
181
- } else {
182
- legacySendAccessibilityEvent(handle._nativeTag, eventType);
183
- }
184
-}
36
+import {
37
+ findHostInstance_DEPRECATED,
38
+ findNodeHandle,
39
+ dispatchCommand,
40
+ sendAccessibilityEvent,
41
+} from './ReactNativePublicCompat';
42
43
// $FlowFixMe[missing-local-annot]
44
function onRecoverableError(error) {
packages/react-native-renderer/src/ReactNativePublicCompat.js
new
+166
@@ -0,0 +1,166 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+import type {HostComponent} from './ReactNativeTypes';
11
+import type {ElementRef, ElementType} from 'react';
12
+
13
+// Modules provided by RN:
14
+import {
15
+ UIManager,
16
+ legacySendAccessibilityEvent,
17
+} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
18
+
19
+import {
20
+ findHostInstance,
21
+ findHostInstanceWithWarning,
22
+} from 'react-reconciler/src/ReactFiberReconciler';
23
+import ReactSharedInternals from 'shared/ReactSharedInternals';
24
+import getComponentNameFromType from 'shared/getComponentNameFromType';
25
+
26
+const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
27
+
28
+export function findHostInstance_DEPRECATED<TElementType: ElementType>(
29
+ componentOrHandle: ?(ElementRef<TElementType> | number),
30
+): ?ElementRef<HostComponent<mixed>> {
31
+ if (__DEV__) {
32
+ const owner = ReactCurrentOwner.current;
33
+ if (owner !== null && owner.stateNode !== null) {
34
+ if (!owner.stateNode._warnedAboutRefsInRender) {
35
+ console.error(
36
+ '%s is accessing findNodeHandle inside its render(). ' +
37
+ 'render() should be a pure function of props and state. It should ' +
38
+ 'never access something that requires stale data from the previous ' +
39
+ 'render, such as refs. Move this logic to componentDidMount and ' +
40
+ 'componentDidUpdate instead.',
41
+ getComponentNameFromType(owner.type) || 'A component',
42
+ );
43
+ }
44
+
45
+ owner.stateNode._warnedAboutRefsInRender = true;
46
+ }
47
+ }
48
+ if (componentOrHandle == null) {
49
+ return null;
50
+ }
51
+ // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
52
+ if (componentOrHandle._nativeTag) {
53
+ // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
54
+ return componentOrHandle;
55
+ }
56
+ // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
57
+ if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
58
+ // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN
59
+ return componentOrHandle.canonical;
60
+ }
61
+ let hostInstance;
62
+ if (__DEV__) {
63
+ hostInstance = findHostInstanceWithWarning(
64
+ componentOrHandle,
65
+ 'findHostInstance_DEPRECATED',
66
+ );
67
+ } else {
68
+ hostInstance = findHostInstance(componentOrHandle);
69
+ }
70
+
71
+ return hostInstance;
72
+}
73
+
74
+export function findNodeHandle(componentOrHandle: any): ?number {
75
+ if (__DEV__) {
76
+ const owner = ReactCurrentOwner.current;
77
+ if (owner !== null && owner.stateNode !== null) {
78
+ if (!owner.stateNode._warnedAboutRefsInRender) {
79
+ console.error(
80
+ '%s is accessing findNodeHandle inside its render(). ' +
81
+ 'render() should be a pure function of props and state. It should ' +
82
+ 'never access something that requires stale data from the previous ' +
83
+ 'render, such as refs. Move this logic to componentDidMount and ' +
84
+ 'componentDidUpdate instead.',
85
+ getComponentNameFromType(owner.type) || 'A component',
86
+ );
87
+ }
88
+
89
+ owner.stateNode._warnedAboutRefsInRender = true;
90
+ }
91
+ }
92
+ if (componentOrHandle == null) {
93
+ return null;
94
+ }
95
+ if (typeof componentOrHandle === 'number') {
96
+ // Already a node handle
97
+ return componentOrHandle;
98
+ }
99
+ if (componentOrHandle._nativeTag) {
100
+ return componentOrHandle._nativeTag;
101
+ }
102
+ if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
103
+ return componentOrHandle.canonical._nativeTag;
104
+ }
105
+ let hostInstance;
106
+ if (__DEV__) {
107
+ hostInstance = findHostInstanceWithWarning(
108
+ componentOrHandle,
109
+ 'findNodeHandle',
110
+ );
111
+ } else {
112
+ hostInstance = findHostInstance(componentOrHandle);
113
+ }
114
+
115
+ if (hostInstance == null) {
116
+ return hostInstance;
117
+ }
118
+
119
+ return hostInstance._nativeTag;
120
+}
121
+
122
+export function dispatchCommand(
123
+ handle: any,
124
+ command: string,
125
+ args: Array<any>,
126
+) {
127
+ if (handle._nativeTag == null) {
128
+ if (__DEV__) {
129
+ console.error(
130
+ "dispatchCommand was called with a ref that isn't a " +
131
+ 'native component. Use React.forwardRef to get access to the underlying native component',
132
+ );
133
+ }
134
+ return;
135
+ }
136
+
137
+ if (handle._internalInstanceHandle != null) {
138
+ const {stateNode} = handle._internalInstanceHandle;
139
+ if (stateNode != null) {
140
+ nativeFabricUIManager.dispatchCommand(stateNode.node, command, args);
141
+ }
142
+ } else {
143
+ UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
144
+ }
145
+}
146
+
147
+export function sendAccessibilityEvent(handle: any, eventType: string) {
148
+ if (handle._nativeTag == null) {
149
+ if (__DEV__) {
150
+ console.error(
151
+ "sendAccessibilityEvent was called with a ref that isn't a " +
152
+ 'native component. Use React.forwardRef to get access to the underlying native component',
153
+ );
154
+ }
155
+ return;
156
+ }
157
+
158
+ if (handle._internalInstanceHandle != null) {
159
+ const {stateNode} = handle._internalInstanceHandle;
160
+ if (stateNode != null) {
161
+ nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType);
162
+ }
163
+ } else {
164
+ legacySendAccessibilityEvent(handle._nativeTag, eventType);
165
+ }
166
+}
packages/react-native-renderer/src/ReactNativeRenderer.js
+7
-143
@@ -7,7 +7,6 @@
7
* @flow
8
*/
9
10
-import type {HostComponent} from './ReactNativeTypes';
10
import type {ReactPortal, ReactNodeList} from 'shared/ReactTypes';
11
import type {ElementRef, Element, ElementType} from 'react';
12
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
@@ -15,8 +14,6 @@ import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
14
import './ReactNativeInjection';
15
16
import {
18
- findHostInstance,
19
- findHostInstanceWithWarning,
17
batchedUpdates as batchedUpdatesImpl,
18
discreteUpdates,
19
createContainer,
@@ -33,10 +30,7 @@ import {
30
} from './legacy-events/ReactGenericBatching';
31
import ReactVersion from 'shared/ReactVersion';
32
// Modules provided by RN:
36
-import {
37
- UIManager,
38
- legacySendAccessibilityEvent,
39
-} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
33
+import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
34
35
import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
36
import {
@@ -45,142 +39,12 @@ import {
39
getInspectorDataForInstance,
40
} from './ReactNativeFiberInspector';
41
import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
48
-import ReactSharedInternals from 'shared/ReactSharedInternals';
49
-import getComponentNameFromType from 'shared/getComponentNameFromType';
50
-
51
-const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
52
-
53
-function findHostInstance_DEPRECATED(
54
- componentOrHandle: any,
55
-): ?React$ElementRef<HostComponent<mixed>> {
56
- if (__DEV__) {
57
- const owner = ReactCurrentOwner.current;
58
- if (owner !== null && owner.stateNode !== null) {
59
- if (!owner.stateNode._warnedAboutRefsInRender) {
60
- console.error(
61
- '%s is accessing findNodeHandle inside its render(). ' +
62
- 'render() should be a pure function of props and state. It should ' +
63
- 'never access something that requires stale data from the previous ' +
64
- 'render, such as refs. Move this logic to componentDidMount and ' +
65
- 'componentDidUpdate instead.',
66
- getComponentNameFromType(owner.type) || 'A component',
67
- );
68
- }
69
-
70
- owner.stateNode._warnedAboutRefsInRender = true;
71
- }
72
- }
73
- if (componentOrHandle == null) {
74
- return null;
75
- }
76
- if (componentOrHandle._nativeTag) {
77
- return componentOrHandle;
78
- }
79
- if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
80
- return componentOrHandle.canonical;
81
- }
82
- let hostInstance;
83
- if (__DEV__) {
84
- hostInstance = findHostInstanceWithWarning(
85
- componentOrHandle,
86
- 'findHostInstance_DEPRECATED',
87
- );
88
- } else {
89
- hostInstance = findHostInstance(componentOrHandle);
90
- }
91
-
92
- return hostInstance;
93
-}
94
-
95
-function findNodeHandle(componentOrHandle: any): ?number {
96
- if (__DEV__) {
97
- const owner = ReactCurrentOwner.current;
98
- if (owner !== null && owner.stateNode !== null) {
99
- if (!owner.stateNode._warnedAboutRefsInRender) {
100
- console.error(
101
- '%s is accessing findNodeHandle inside its render(). ' +
102
- 'render() should be a pure function of props and state. It should ' +
103
- 'never access something that requires stale data from the previous ' +
104
- 'render, such as refs. Move this logic to componentDidMount and ' +
105
- 'componentDidUpdate instead.',
106
- getComponentNameFromType(owner.type) || 'A component',
107
- );
108
- }
109
-
110
- owner.stateNode._warnedAboutRefsInRender = true;
111
- }
112
- }
113
- if (componentOrHandle == null) {
114
- return null;
115
- }
116
- if (typeof componentOrHandle === 'number') {
117
- // Already a node handle
118
- return componentOrHandle;
119
- }
120
- if (componentOrHandle._nativeTag) {
121
- return componentOrHandle._nativeTag;
122
- }
123
- if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) {
124
- return componentOrHandle.canonical._nativeTag;
125
- }
126
- let hostInstance;
127
- if (__DEV__) {
128
- hostInstance = findHostInstanceWithWarning(
129
- componentOrHandle,
130
- 'findNodeHandle',
131
- );
132
- } else {
133
- hostInstance = findHostInstance(componentOrHandle);
134
- }
135
-
136
- if (hostInstance == null) {
137
- return hostInstance;
138
- }
139
-
140
- return hostInstance._nativeTag;
141
-}
142
-
143
-function dispatchCommand(handle: any, command: string, args: Array<any>) {
144
- if (handle._nativeTag == null) {
145
- if (__DEV__) {
146
- console.error(
147
- "dispatchCommand was called with a ref that isn't a " +
148
- 'native component. Use React.forwardRef to get access to the underlying native component',
149
- );
150
- }
151
- return;
152
- }
153
-
154
- if (handle._internalInstanceHandle != null) {
155
- const {stateNode} = handle._internalInstanceHandle;
156
- if (stateNode != null) {
157
- nativeFabricUIManager.dispatchCommand(stateNode.node, command, args);
158
- }
159
- } else {
160
- UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args);
161
- }
162
-}
163
-
164
-function sendAccessibilityEvent(handle: any, eventType: string) {
165
- if (handle._nativeTag == null) {
166
- if (__DEV__) {
167
- console.error(
168
- "sendAccessibilityEvent was called with a ref that isn't a " +
169
- 'native component. Use React.forwardRef to get access to the underlying native component',
170
- );
171
- }
172
- return;
173
- }
174
-
175
- if (handle._internalInstanceHandle != null) {
176
- const {stateNode} = handle._internalInstanceHandle;
177
- if (stateNode != null) {
178
- nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType);
179
- }
180
- } else {
181
- legacySendAccessibilityEvent(handle._nativeTag, eventType);
182
- }
183
-}
42
+import {
43
+ findHostInstance_DEPRECATED,
44
+ findNodeHandle,
45
+ dispatchCommand,
46
+ sendAccessibilityEvent,
47
+} from './ReactNativePublicCompat';
48
49
// $FlowFixMe[missing-local-annot]
50
function onRecoverableError(error) {