O hirunewani blog

Reactでrefをマージする

Created at

Propsから受け取ったrefを内部的なrefとマージする方法を紹介する。

UIライブラリなどをReactで作成していると、Propsから受け取ったrefを内部的なrefとマージしたくなることがある。 次のようなコードを書けばいい。

import { useMemo } from "react";

export type ReactRef<T> = React.RefCallback<T> | React.MutableRefObject<T>;

export function assignRef<T = unknown>(
  ref: ReactRef<T> | null | undefined,
  value: T,
) {
  if (ref === null || ref === undefined) return;

  if (typeof ref === "function") {
    ref(value);
    return;
  }

  try {
    ref.current = value;
  } catch (error) {
    throw new Error(`Cannot assign value '${value}' to ref '${ref}'`);
  }
}

export function mergeRefs<T>(...refs: (ReactRef<T> | null | undefined)[]) {
  return (node: T | null) => {
    refs.forEach((ref) => {
      assignRef(ref, node);
    });
  };
}

export function useMergeRefs<T>(...refs: (ReactRef<T> | null | undefined)[]) {
  return useMemo(() => mergeRefs(...refs), refs);
}