From 0a4f5e132ca003c2ae1d3498596a3a0cdf6f72f4 Mon Sep 17 00:00:00 2001 From: DS Boyce <260543580+ds-boyce@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:32:15 -0700 Subject: [PATCH] Update mergeRefs util for React 19 (#11108) --- eslint-suppressions.json | 5 ----- src/lib/merge-refs.ts | 43 ++++++++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 8c695aabf7..c1d213d875 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -984,11 +984,6 @@ "count": 1 } }, - "src/lib/merge-refs.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 1 - } - }, "src/lib/notifications/notifications.ts": { "@typescript-eslint/no-floating-promises": { "count": 5 diff --git a/src/lib/merge-refs.ts b/src/lib/merge-refs.ts index bf8cbfddaa..d2b187e1e9 100644 --- a/src/lib/merge-refs.ts +++ b/src/lib/merge-refs.ts @@ -1,3 +1,22 @@ +import {type Ref, type RefCallback} from 'react' + +/** + * Assigns a value to a ref. + * @param ref The ref to assign the value to. + * @param value The value to assign to the ref. + * @returns The ref cleanup callback, if any. + */ +function assignRef( + ref: Ref | undefined | null, + value: T | null, +): ReturnType> { + if (typeof ref === 'function') { + return ref(value) + } else if (ref) { + ref.current = value + } +} + /** * This TypeScript function merges multiple React refs into a single ref callback. * When developing low level UI components, it is common to have to use a local ref @@ -12,16 +31,18 @@ * @returns The function `mergeRefs` is being returned. It takes an array of mutable or legacy refs and * returns a ref callback function that can be used to merge multiple refs into a single ref. */ -export function mergeRefs( - refs: Array | React.Ref | undefined>, -): React.RefCallback { - return value => { - refs.forEach(ref => { - if (typeof ref === 'function') { - ref(value) - } else if (ref != null) { - ;(ref as React.MutableRefObject).current = value - } - }) +export function mergeRefs(refs: (Ref | undefined)[]): Ref { + return (value: T | null) => { + const cleanups: (() => void)[] = [] + + for (const ref of refs) { + const cleanup = assignRef(ref, value) + const isCleanup = typeof cleanup === 'function' + cleanups.push(isCleanup ? cleanup : () => assignRef(ref, null)) + } + + return () => { + for (const cleanup of cleanups) cleanup() + } } }