🍒

useRefの基本と使い方

に公開

useRefは、React 16.8から導入された、再レンダリングなしで値やDOM要素を更新できるReactフック。

「DOMに直接アクセスしたいとき」「再レンダリングなしで値を保持・更新したいとき」「前回の値や状態を記録しておきたいとき」などに便利。

使い方は2種類ある。

再レンダリングなしで値を保持・更新

  • .currentで操作する。
  • 何度でも変更でき、再レンダリングは起きない。
  • useStateを使うと、値を変更するたびに再レンダリングが走り、状態の更新が遅延(非同期)して正しい値が取れないことがある。このようなときにuseRefを使える。
import { useRef, useState } from 'react';

const Component = () => {
 // 再レンダリングなしで値を保持・更新できる
  const inputValueRef = useRef<string>('');
  const [savedValue, setSavedValue] = useState('');

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    inputValueRef.current = e.target.value;
  };

  const handleSave = () => {
    setSavedValue(inputValueRef.current);
  };

  return (
    <div>
      <input type="text" onChange={handleChange} />
      <button onClick={handleSave}>保存</button>
      <div>保存された値: {savedValue}</div>
    </div>
  );
};
export default Component;

DOM操作で使う

  • DOM要素に直接アクセスできる。
  • focus() を使ってフォーカスを当てるなど、直接操作をしたいときに便利。
  • イベントや条件に応じて、手動でDOMを操作できる。
import { useRef } from 'react';

const Component = () => {
  const inputRef = useRef<HTMLInputElement>(null);

  const handleFocus = () => {
    // input要素にフォーカスを当てる
    inputRef.current?.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={handleFocus}>フォーカスを当てる</button>
    </div>
  );
};

export default Component;

注意

「値の保持」と「DOM要素の参照」は、useRefを別々に作成する必要がある。同じuseRefで両方の用途を同時に扱うことはできない。

値を保持・更新の派生: 関数を動的に保持することもできる

  • 動的に関数を入れ替えたいときに使える。
  • 再レンダリングなしで関数を保持できる。
最新の関数を保持し、常にそれを実行する例
import { useEffect, useRef } from 'react';

const Component = () => {
  const handlerRef = useRef<() => void>(() => {});

  const handleClick = () => {
    console.log('最新のクリック処理!');
  };

  // 毎回最新の関数をhandlerRefに入れておく
  useEffect(() => {
    handlerRef.current = handleClick;
  });

  useEffect(() => {
    const interval = setInterval(() => {
      handlerRef.current(); // 常に最新の関数が呼ばれる
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return <div>何かのUI</div>;
};

Discussion