@samitouri / QOS-React-2 / commits / eb616a12f1

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) {