useMergeRef.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import * as React from 'react';
  2. import { assignRef } from './assignRef';
  3. import { useCallbackRef } from './useRef';
  4. var useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
  5. var currentValues = new WeakMap();
  6. /**
  7. * Merges two or more refs together providing a single interface to set their value
  8. * @param {RefObject|Ref} refs
  9. * @returns {MutableRefObject} - a new ref, which translates all changes to {refs}
  10. *
  11. * @see {@link mergeRefs} a version without buit-in memoization
  12. * @see https://github.com/theKashey/use-callback-ref#usemergerefs
  13. * @example
  14. * const Component = React.forwardRef((props, ref) => {
  15. * const ownRef = useRef();
  16. * const domRef = useMergeRefs([ref, ownRef]); // 👈 merge together
  17. * return <div ref={domRef}>...</div>
  18. * }
  19. */
  20. export function useMergeRefs(refs, defaultValue) {
  21. var callbackRef = useCallbackRef(defaultValue || null, function (newValue) {
  22. return refs.forEach(function (ref) { return assignRef(ref, newValue); });
  23. });
  24. // handle refs changes - added or removed
  25. useIsomorphicLayoutEffect(function () {
  26. var oldValue = currentValues.get(callbackRef);
  27. if (oldValue) {
  28. var prevRefs_1 = new Set(oldValue);
  29. var nextRefs_1 = new Set(refs);
  30. var current_1 = callbackRef.current;
  31. prevRefs_1.forEach(function (ref) {
  32. if (!nextRefs_1.has(ref)) {
  33. assignRef(ref, null);
  34. }
  35. });
  36. nextRefs_1.forEach(function (ref) {
  37. if (!prevRefs_1.has(ref)) {
  38. assignRef(ref, current_1);
  39. }
  40. });
  41. }
  42. currentValues.set(callbackRef, refs);
  43. }, [refs]);
  44. return callbackRef;
  45. }