9.1 useRef

refは、レンダリングに不要な値を保持する。

const intervalId = useRef<number | null>(null);

ref更新は再レンダリングを起こさない。

9.2 DOM参照

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

  return (
    <>
      <input ref={inputRef} />
      <button
        type="button"
        onClick={() => inputRef.current?.focus()}
      >
        フォーカス
      </button>
    </>
  );
}

DOM操作はフォーカス、スクロール、計測、メディア制御など必要最小限にする。

9.3 React 19のref prop

React 19では、関数コンポーネントがrefをpropsとして受け取れる。

type InputProps = React.ComponentPropsWithoutRef<"input"> & {
  ref?: React.Ref<HTMLInputElement>;
};

function Input({ ref, ...props }: InputProps) {
  return <input ref={ref} {...props} />;
}

既存コードではforwardRefも広く存在するため、読み方は理解しておく。

9.4 useImperativeHandle

親へ公開する命令的APIを限定する。

type DialogHandle = {
  open: () => void;
  close: () => void;
};

function Dialog({
  ref,
}: {
  ref: React.Ref<DialogHandle>;
}) {
  const dialogRef = useRef<HTMLDialogElement>(null);

  useImperativeHandle(ref, () => ({
    open() {
      dialogRef.current?.showModal();
    },
    close() {
      dialogRef.current?.close();
    },
  }), []);

  return <dialog ref={dialogRef}>内容</dialog>;
}

通常のpropsで表現できる状態は、命令的APIにしない。