Skip to content
38

composeRefs

Merges several refs into one callback ref, so a part can keep its own ref and still forward the element. Returns React 19 ref cleanups.

Example

Installation

npx shadcn@latest add https://hirael.com/r/compose-refs.json

Usage

import { composeRefs } from "@/lib/compose-refs"

Paths assume the default @/ alias from your components.json.

API

composeRefs()

ParameterTypeDefault
...refs

Object or callback refs to receive the node; `undefined` entries are skipped.

(React.Ref<T> | undefined)[]none
ReturnsReact.RefCallback<T>

Source

import type * as React from 'react';

const setRef = <T>(ref: React.Ref<T> | undefined, node: T | null) => {
  if (typeof ref === 'function') return ref(node);
  if (ref) ref.current = node;
};

/**
 * Merges refs, returning React 19 callback-ref cleanups so consumer refs are torn down, not called with null.
 * @param refs Object or callback refs to receive the node; `undefined` entries are skipped.
 */
export const composeRefs =
  <T>(...refs: (React.Ref<T> | undefined)[]): React.RefCallback<T> =>
  (node) => {
    const cleanups = refs.map((ref) => setRef(ref, node));
    if (!cleanups.some((cleanup) => typeof cleanup === 'function')) return;

    return () => {
      cleanups.forEach((cleanup, i) => {
        if (typeof cleanup === 'function') cleanup();
        else setRef(refs[i], null);
      });
    };
  };

Shipped