Skip to main content

composeRefs

A utility that composes multiple React refs (callback refs and RefObjects) into a single callback ref. Useful when you need to assign a DOM node to more than one ref at the same time.

For the React hook version that wraps this in useCallback for stability, see useComposedRefs in @ngrok/mantle/hooks.

import { composeRefs } from "@ngrok/mantle/utils";

Usage

Forwarding a ref while keeping an internal ref

The most common use case: accept a ref prop from the parent while keeping an internal ref for the component itself.

import { useRef, type ComponentProps } from "react";import { composeRefs } from "@ngrok/mantle/utils"; const MyInput = ({ ref: forwardedRef, ...props }: ComponentProps<"input">) => {	const internalRef = useRef<HTMLInputElement>(null); 	return <input ref={composeRefs(internalRef, forwardedRef)} {...props} />;};

With multiple refs

import { useRef } from "react";import { composeRefs } from "@ngrok/mantle/utils"; function Example() {	const focusRef = useRef<HTMLButtonElement>(null);	const measureRef = useRef<HTMLButtonElement>(null); 	return <button ref={composeRefs(focusRef, measureRef)}>Click me</button>;}

With callback refs

composeRefs accepts any mix of RefObjects and callback refs:

import { useRef } from "react";import { composeRefs } from "@ngrok/mantle/utils"; function Example() {	const objectRef = useRef<HTMLDivElement>(null);	const callbackRef = (node: HTMLDivElement | null) => {		if (node) {			console.log("mounted", node);		}	}; 	return <div ref={composeRefs(objectRef, callbackRef)} />;}

API

function composeRefs<T>(...refs: PossibleRef<T>[]): RefCallback<T>; type PossibleRef<T> = React.Ref<T> | undefined;

Accepts any number of refs (callback refs, RefObjects, or undefined). Returns a single callback ref that, when called with a node, assigns the node to every given ref. undefined refs are safely skipped. When a callback ref returns a React 19 ref cleanup function, the composed ref propagates it, so each cleanup runs on unmount.