diff --git a/Libraries/Utilities/setAndForwardRef.js b/Libraries/Utilities/setAndForwardRef.js new file mode 100644 index 0000000000000000000000000000000000000000..e67b530b9a933b68e219e2b8cec2a66dc8f51323 --- /dev/null +++ b/Libraries/Utilities/setAndForwardRef.js @@ -0,0 +1,68 @@ +/** + * 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. + * + * @format + * @flow + */ + +'use strict' + +import type { ElementRef, Ref } from 'react' + +type Args = $ReadOnly<{| + getForwardedRef: () => ?Ref, + setLocalRef: (ref: ElementRef) => mixed +|}> + +/** + * This is a helper function for when a component needs to be able to forward a ref + * to a child component, but still needs to have access to that component as part of + * its implementation. + * + * Its main use case is in wrappers for native components. + * + * Usage: + * + * class MyView extends React.Component { + * _nativeRef = null; + * + * _setNativeRef = setAndForwardRef({ + * getForwardedRef: () => this.props.forwardedRef, + * setLocalRef: ref => { + * this._nativeRef = ref; + * }, + * }); + * + * render() { + * return ; + * } + * } + * + * const MyViewWithRef = React.forwardRef((props, ref) => ( + * + * )); + * + * module.exports = MyViewWithRef; + */ + +function setAndForwardRef({ getForwardedRef, setLocalRef }: Args): (ref: ElementRef) => void { + return function forwardRef(ref: ElementRef) { + const forwardedRef = getForwardedRef() + + setLocalRef(ref) + + // Forward to user ref prop (if one has been specified) + if (typeof forwardedRef === 'function') { + // Handle function-based refs. String-based refs are handled as functions. + forwardedRef(ref) + } else if (typeof forwardedRef === 'object' && forwardedRef != null) { + // Handle createRef-based refs + forwardedRef.current = ref + } + } +} + +module.exports = setAndForwardRef