UGA Boxxx

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

【React】ref属性にrefオブジェクトではなく関数を渡す

Reactのjsxで、ref属性に関数を渡すやり方を見かけたので調べた

react.dev

ref属性に関数を渡すやり方はref callback functionと呼ばれ、refを利用してDOM要素やコンポーネントへの参照を取得する際に使う

基本構文

ref属性に関数を渡すことで、その関数がDOM要素やコンポーネントインスタンスを受け取る形で呼び出される

function MyComponent() {
  const handleRef = (node) => {
    if (node) {
      // nodeがDOM要素にマウントされたとき
      console.log('Ref received:', node);
    } else {
      // nodeがアンマウントされたとき
      console.log('Ref cleared');
    }
  };

  return <div ref={handleRef}>Hello</div>;
}

動作のポイント

  1. マウント時とアンマウント時に呼び出される

    • マウント時: 引数にDOM要素やコンポーネントが渡される
    • アンマウント時: 引数としてnullが渡される
  2. レンダリング時にも実行される
    レンダリングが発生すると、新しい要素に対して再度ref callbackが呼び出される

使用例

1. DOM要素の制御

ref callback functionで取得したDOM要素に対して、スクロールやフォーカスなどの操作を行う

function FocusInput() {
  const inputRef = (node) => {
    if (node) {
      node.focus();
    }
  };

  return <input ref={inputRef} type="text" />;
}

2. 条件付き処理

特定の条件でのみ処理を実行したい場合

function ConditionalRef() {
  const handleRef = (node) => {
    if (node && node.tagName === 'BUTTON') {
      console.log('Button element:', node);
    }
  };

  return <button ref={handleRef}>Click Me</button>;
}

注意点としては、リレンダリングのたびにref callbackが実行されるため、不必要な処理が実行されないようにすること

コードをコピーする
const handleRef = useCallback((node) => {
  if (node) {
    console.log('Ref received:', node);
  }
}, []); // 再生成を防ぐため useCallback を使用