UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【React】複数のuseRefをまとめたい

外側から受け取ったrefとは別に、コンポーネント内部で定義したrefも一緒に子コンポーネントに渡したい場合を調べた

調べたところ、カスタムhookで作る必要があった

useMergeRefという名でよくutilとして実装されている模様

実装例:

import { useCallback } from 'react';

function useMergeRef<T>(...refs: Array<React.Ref<T> | undefined>) {
  return useCallback((node: T | null) => {
    refs.forEach(ref => {
      if (!ref) return;

      if (typeof ref === 'function') {
        ref(node); // 関数型refの場合、直接呼び出す
      } else if (ref && 'current' in ref) {
        (ref as React.MutableRefObject<T | null>).current = node; // オブジェクト型refの場合、currentに設定
      }
    });
  }, [refs]);
}

export default useMergeRef;

使い方

外部refと内部refをマージして渡す

import React, { forwardRef, useRef } from 'react';
import useMergeRef from './useMergeRef';

type Props = {
  externalRef?: React.Ref<HTMLDivElement>;
};

const MyComponent = forwardRef<HTMLDivElement, Props>(({ externalRef }, forwardedRef) => {
  const internalRef = useRef<HTMLDivElement>(null);

  const mergedRef = useMergeRef(internalRef, externalRef, forwardedRef);

  return <div ref={mergedRef}>Hello, World!</div>;
});

export default MyComponent;

これで外部refと内部refを簡単に統合して扱えるようになった