useComposedRefs.ts32 lines · main
1import { Ref, useCallback } from 'react'
2
3type PossibleRef<T> = Ref<T> | undefined
4
5/**
6 * Set a given ref to a given value
7 * This utility takes care of different types of refs: callback refs and RefObject(s)
8 */
9function setRef<T>(ref: PossibleRef<T>, value: T) {
10 if (typeof ref === 'function') {
11 ref(value)
12 } else if (ref !== null && ref !== undefined) {
13 ;(ref as React.MutableRefObject<T>).current = value
14 }
15}
16
17/**
18 * A utility to compose multiple refs together
19 * Accepts callback refs and RefObject(s)
20 */
21export function composeRefs<T>(...refs: PossibleRef<T>[]) {
22 return (node: T) => refs.forEach((ref) => setRef(ref, node))
23}
24
25/**
26 * A custom hook that composes multiple refs
27 * Accepts callback refs and RefObject(s)
28 */
29export function useComposedRefs<T>(...refs: PossibleRef<T>[]) {
30 // eslint-disable-next-line react-hooks/exhaustive-deps
31 return useCallback(composeRefs(...refs), refs)
32}