-
Notifications
You must be signed in to change notification settings - Fork 47.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract duplicated methods in Fabric and the legacy renderer to a sha…
…red 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).
- Loading branch information
1 parent
49f7410
commit eb616a1
Showing
3 changed files
with
179 additions
and
292 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
166 changes: 166 additions & 0 deletions
166
packages/react-native-renderer/src/ReactNativePublicCompat.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import type {HostComponent} from './ReactNativeTypes'; | ||
import type {ElementRef, ElementType} from 'react'; | ||
|
||
// Modules provided by RN: | ||
import { | ||
UIManager, | ||
legacySendAccessibilityEvent, | ||
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; | ||
|
||
import { | ||
findHostInstance, | ||
findHostInstanceWithWarning, | ||
} from 'react-reconciler/src/ReactFiberReconciler'; | ||
import ReactSharedInternals from 'shared/ReactSharedInternals'; | ||
import getComponentNameFromType from 'shared/getComponentNameFromType'; | ||
|
||
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; | ||
|
||
export function findHostInstance_DEPRECATED<TElementType: ElementType>( | ||
componentOrHandle: ?(ElementRef<TElementType> | number), | ||
): ?ElementRef<HostComponent<mixed>> { | ||
if (__DEV__) { | ||
const owner = ReactCurrentOwner.current; | ||
if (owner !== null && owner.stateNode !== null) { | ||
if (!owner.stateNode._warnedAboutRefsInRender) { | ||
console.error( | ||
'%s is accessing findNodeHandle inside its render(). ' + | ||
'render() should be a pure function of props and state. It should ' + | ||
'never access something that requires stale data from the previous ' + | ||
'render, such as refs. Move this logic to componentDidMount and ' + | ||
'componentDidUpdate instead.', | ||
getComponentNameFromType(owner.type) || 'A component', | ||
); | ||
} | ||
|
||
owner.stateNode._warnedAboutRefsInRender = true; | ||
} | ||
} | ||
if (componentOrHandle == null) { | ||
return null; | ||
} | ||
// $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN | ||
if (componentOrHandle._nativeTag) { | ||
// $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN | ||
return componentOrHandle; | ||
} | ||
// $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN | ||
if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { | ||
// $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN | ||
return componentOrHandle.canonical; | ||
} | ||
let hostInstance; | ||
if (__DEV__) { | ||
hostInstance = findHostInstanceWithWarning( | ||
componentOrHandle, | ||
'findHostInstance_DEPRECATED', | ||
); | ||
} else { | ||
hostInstance = findHostInstance(componentOrHandle); | ||
} | ||
|
||
return hostInstance; | ||
} | ||
|
||
export function findNodeHandle(componentOrHandle: any): ?number { | ||
if (__DEV__) { | ||
const owner = ReactCurrentOwner.current; | ||
if (owner !== null && owner.stateNode !== null) { | ||
if (!owner.stateNode._warnedAboutRefsInRender) { | ||
console.error( | ||
'%s is accessing findNodeHandle inside its render(). ' + | ||
'render() should be a pure function of props and state. It should ' + | ||
'never access something that requires stale data from the previous ' + | ||
'render, such as refs. Move this logic to componentDidMount and ' + | ||
'componentDidUpdate instead.', | ||
getComponentNameFromType(owner.type) || 'A component', | ||
); | ||
} | ||
|
||
owner.stateNode._warnedAboutRefsInRender = true; | ||
} | ||
} | ||
if (componentOrHandle == null) { | ||
return null; | ||
} | ||
if (typeof componentOrHandle === 'number') { | ||
// Already a node handle | ||
return componentOrHandle; | ||
} | ||
if (componentOrHandle._nativeTag) { | ||
return componentOrHandle._nativeTag; | ||
} | ||
if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { | ||
return componentOrHandle.canonical._nativeTag; | ||
} | ||
let hostInstance; | ||
if (__DEV__) { | ||
hostInstance = findHostInstanceWithWarning( | ||
componentOrHandle, | ||
'findNodeHandle', | ||
); | ||
} else { | ||
hostInstance = findHostInstance(componentOrHandle); | ||
} | ||
|
||
if (hostInstance == null) { | ||
return hostInstance; | ||
} | ||
|
||
return hostInstance._nativeTag; | ||
} | ||
|
||
export function dispatchCommand( | ||
handle: any, | ||
command: string, | ||
args: Array<any>, | ||
) { | ||
if (handle._nativeTag == null) { | ||
if (__DEV__) { | ||
console.error( | ||
"dispatchCommand was called with a ref that isn't a " + | ||
'native component. Use React.forwardRef to get access to the underlying native component', | ||
); | ||
} | ||
return; | ||
} | ||
|
||
if (handle._internalInstanceHandle != null) { | ||
const {stateNode} = handle._internalInstanceHandle; | ||
if (stateNode != null) { | ||
nativeFabricUIManager.dispatchCommand(stateNode.node, command, args); | ||
} | ||
} else { | ||
UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args); | ||
} | ||
} | ||
|
||
export function sendAccessibilityEvent(handle: any, eventType: string) { | ||
if (handle._nativeTag == null) { | ||
if (__DEV__) { | ||
console.error( | ||
"sendAccessibilityEvent was called with a ref that isn't a " + | ||
'native component. Use React.forwardRef to get access to the underlying native component', | ||
); | ||
} | ||
return; | ||
} | ||
|
||
if (handle._internalInstanceHandle != null) { | ||
const {stateNode} = handle._internalInstanceHandle; | ||
if (stateNode != null) { | ||
nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType); | ||
} | ||
} else { | ||
legacySendAccessibilityEvent(handle._nativeTag, eventType); | ||
} | ||
} |
Oops, something went wrong.