setAndForwardRef.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /**
  2. * Copyright (c) Facebook, Inc. and its 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. * @format
  8. * @flow
  9. */
  10. 'use strict';
  11. import type {ElementRef, Ref} from 'react';
  12. type Args = $ReadOnly<{|
  13. getForwardedRef: () => ?Ref<any>,
  14. setLocalRef: (ref: ElementRef<any>) => mixed,
  15. |}>;
  16. /**
  17. * This is a helper function for when a component needs to be able to forward a ref
  18. * to a child component, but still needs to have access to that component as part of
  19. * its implementation.
  20. *
  21. * Its main use case is in wrappers for native components.
  22. *
  23. * Usage:
  24. *
  25. * class MyView extends React.Component {
  26. * _nativeRef = null;
  27. *
  28. * _setNativeRef = setAndForwardRef({
  29. * getForwardedRef: () => this.props.forwardedRef,
  30. * setLocalRef: ref => {
  31. * this._nativeRef = ref;
  32. * },
  33. * });
  34. *
  35. * render() {
  36. * return <View ref={this._setNativeRef} />;
  37. * }
  38. * }
  39. *
  40. * const MyViewWithRef = React.forwardRef((props, ref) => (
  41. * <MyView {...props} forwardedRef={ref} />
  42. * ));
  43. *
  44. * module.exports = MyViewWithRef;
  45. */
  46. function setAndForwardRef({
  47. getForwardedRef,
  48. setLocalRef,
  49. }: Args): (ref: ElementRef<any>) => void {
  50. return function forwardRef(ref: ElementRef<any>) {
  51. const forwardedRef = getForwardedRef();
  52. setLocalRef(ref);
  53. // Forward to user ref prop (if one has been specified)
  54. if (typeof forwardedRef === 'function') {
  55. // Handle function-based refs. String-based refs are handled as functions.
  56. forwardedRef(ref);
  57. } else if (typeof forwardedRef === 'object' && forwardedRef != null) {
  58. // Handle createRef-based refs
  59. forwardedRef.current = ref;
  60. }
  61. };
  62. }
  63. module.exports = setAndForwardRef;