カテゴリ: React 更新日: 2026/03/23

TypeScriptでrefを型定義する方法(useRef)を完全解説!初心者でもわかるReactの基本

TypeScriptでrefを型定義する方法(useRef)
TypeScriptでrefを型定義する方法(useRef)

先生と生徒の会話形式で理解しよう

生徒

「Reactでrefってよく聞きますけど、TypeScriptを使うときは型をどうやって書くんですか?」

先生

「refはコンポーネント内で直接DOM要素や値にアクセスするために使います。TypeScriptでは型をしっかり付けて使うと安全ですよ。」

生徒

「DOM要素って何ですか?」

先生

「DOM要素とは、HTMLのタグそのものです。例えば<input><div>のことを指します。」

生徒

「なるほど!じゃあTypeScriptでrefを型安全に書く方法を知りたいです!」

先生

「それでは具体的にコードを使って解説していきましょう。」

1. useRefの基本的な使い方

1. useRefの基本的な使い方
1. useRefの基本的な使い方

useRefは、Reactで「参照」を保持するために使うフックです。参照とは、特定の要素や値を記憶しておく箱のようなものです。useRefでよく使うのが、フォームの入力欄(inputタグ)にアクセスするときです。


import React, { useRef } from "react";

const InputFocus: React.FC = () => {
  const inputRef = useRef<HTMLInputElement>(null);

  const handleClick = () => {
    if (inputRef.current) {
      inputRef.current.focus();
    }
  };

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

export default InputFocus;
(画面に入力欄とボタンが表示され、ボタンを押すと入力欄にカーソルが移動します)

この例ではuseRef<HTMLInputElement>(null)と書いて、refの型を「HTMLのinput要素」と定義しています。これにより、TypeScriptがinputRef.currentを使うときに正しく補完してくれるようになります。

2. 数値や文字列の値を保持する場合

2. 数値や文字列の値を保持する場合
2. 数値や文字列の値を保持する場合

useRefはDOM要素だけでなく、単純な値を保持することもできます。例えば数値や文字列を保存しておきたいときに便利です。


import React, { useRef } from "react";

const Counter: React.FC = () => {
  const countRef = useRef<number>(0);

  const handleIncrement = () => {
    countRef.current += 1;
    console.log("現在の値:", countRef.current);
  };

  return (
    <div>
      <button onClick={handleIncrement}>カウントアップ</button>
    </div>
  );
};

export default Counter;
(ボタンをクリックすると、コンソールにカウントが1ずつ増えて表示されます)

ここではuseRef<number>(0)と書くことで、数値専用の箱を作っています。これにより、誤って文字列を代入しようとするとTypeScriptがエラーを出してくれるので安心です。

3. 型を省略するとどうなる?

3. 型を省略するとどうなる?
3. 型を省略するとどうなる?

もしuseRef(null)とだけ書くと、型はMutableRefObject<undefined>として推論されてしまい、実際のDOM操作ではエラーになる可能性があります。そのため、基本的には必ず型を明示して書くことをおすすめします。


const inputRef = useRef<HTMLInputElement | null>(null);

このように「| null」を付けることで、「まだ要素が存在しないかもしれない」という可能性も正しく表現できます。

4. refを使うときの注意点

4. refを使うときの注意点
4. refを使うときの注意点

初心者がよく間違えるポイントを整理しておきましょう。

  • useRefは直接画面に表示されるものではなく、裏で参照を保持するためのもの
  • DOM要素に使うときは必ず適切な型(例:HTMLDivElementHTMLInputElement)を指定する
  • 数値や文字列を保持するときはその型(例:numberstring)を指定する
  • refを使わずに済む場合はstateを優先するのが基本

例えば、「フォームの入力内容を取得して表示したい」というときはstateを使いますが、「ボタンを押したら入力欄にフォーカスを当てたい」というときはrefを使うのが適切です。

5. よく使うDOM要素と型の一覧

5. よく使うDOM要素と型の一覧
5. よく使うDOM要素と型の一覧

最後に、ReactとTypeScriptでrefを使うときによく登場するDOM要素と型の対応表を載せておきます。

  • <input>HTMLInputElement
  • <textarea>HTMLTextAreaElement
  • <button>HTMLButtonElement
  • <div>HTMLDivElement
  • <form>HTMLFormElement

これらを覚えておくと、refの型を付けるときにすぐに書けるようになります。

まとめ

まとめ
まとめ

この記事では、React開発における重要なフックの一つであるuseRefを、TypeScriptで型安全に活用する方法について詳しく解説してきました。ReactとTypeScriptを組み合わせて使用する際、useRefの型定義を正しく行うことは、実行時の予期せぬエラーを防ぎ、エディタの強力な補完機能を最大限に引き出すために不可欠なスキルです。

useRefは、大きく分けて二つの役割を持っています。一つは、特定のDOM要素(inputタグやdivタグなど)に直接アクセスして、フォーカス制御やスクロール位置の取得などを行う役割です。もう一つは、レンダリングを発生させずに、コンポーネントの再描画後も保持し続けたい「書き換え可能な値」を管理する役割です。これらを用途に合わせて正しく使い分けることが、クリーンなコードを書くための第一歩となります。

TypeScriptでのuseRefの型定義パターン

実務でよく使われる、より実践的なuseRefの型定義の書き方を復習しましょう。特にDOM要素を操作する場合は、初期値にnullを渡し、ジェネリクスを使用してHTML要素の型を指定するのが標準的な書き方です。


import React, { useRef, useEffect } from "react";

const VideoPlayer: React.FC = () => {
  // ビデオ要素への参照を型定義(HTMLVideoElement)
  const videoRef = useRef<HTMLVideoElement>(null);

  const handlePlay = () => {
    // currentが存在するかチェック(オプショナルチェイニング)
    videoRef.current?.play();
  };

  const handlePause = () => {
    if (videoRef.current) {
      videoRef.current.pause();
    }
  };

  return (
    
); }; export default VideoPlayer;
(画面にビデオとボタンが表示され、再生ボタンを押すと動画が始まり、停止ボタンを押すと動画が止まります)

なぜ型定義が必要なのか:SEOと保守性の観点から

TypeScriptで厳格に型を定義することは、単にエラーを防ぐだけではありません。大規模なプロジェクトにおいて、どのコンポーネントがどのDOM要素を操作しているのかを明示的にすることで、コードの可読性が飛躍的に向上します。これは開発効率を高めるだけでなく、結果として質の高いWebサイトを素早く提供することに繋がり、間接的にSEO(検索エンジン最適化)の成果にも寄与します。

また、検索エンジンに評価されるアクセシビリティの高いサイトを作るためには、適切なタイミングでフォーカス制御を行うことが求められます。例えば、モーダルウィンドウを開いた際に入力項目へ自動でフォーカスを移すといった処理は、useRefとTypeScriptを組み合わせることで、論理的なミスなく実装することが可能になります。

DOM操作以外のuseRef活用法

useRefは「値の保持」にも非常に有効です。useStateを使うと値が更新されるたびにコンポーネントが再レンダリングされますが、useRefは値を更新しても再レンダリングが発生しません。この特性を利用して、以前のpropsの値を保持したり、タイマーのID(setIntervalの戻り値)を保存したりする場合によく使われます。


import React, { useRef, useState } from "react";

const TimerApp: React.FC = () => {
  const [seconds, setSeconds] = useState<number>(0);
  // タイマーIDを保持するためのref。初期値はnull、型はNodeJS.Timeoutまたはnumber
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const startTimer = () => {
    if (timerRef.current !== null) return; // 二重起動防止
    timerRef.current = setInterval(() => {
      setSeconds((prev) => prev + 1);
    }, 1000);
  };

  const stopTimer = () => {
    if (timerRef.current !== null) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
  };

  return (
    

経過時間: {seconds}秒

); }; export default TimerApp;
(スタートボタンを押すと秒数が増え始め、ストップボタンを押すとカウントが停止します)

学習のポイント振り返り

最後に、初心者がuseRefとTypeScriptを扱う際に意識すべきポイントをまとめます。第一に、ジェネリクス(< >)の中には対象となるHTML要素の正確な型を入れること。第二に、初期値にはnullを指定し、使用時には必ずnullチェックを行うこと。第三に、何でもrefで解決しようとせず、データの同期が必要な場合はuseStateを使用するという原則を忘れないことです。

TypeScriptの学習は最初は難しく感じるかもしれませんが、一度型定義の便利さを知れば、型のないJavaScriptでの開発には戻れなくなるほど強力なツールです。今回学んだ基礎を土台にして、さらに高度なReact Hooksやライブラリの活用に挑戦していきましょう。

先生と生徒の振り返り会話

生徒

「先生、ありがとうございました!useRefに型を付ける方法がようやくスッキリ理解できました。今までなんとなくanyを使ってしまっていた部分もあったので、これからはちゃんとHTMLInputElementとかを指定するようにします。」

先生

「それは素晴らしい進歩ですね。anyを使ってしまうとTypeScriptの良さが消えてしまいますから。特にDOM要素は種類が多いので、この記事にある対応表を参考に、正確な型を付ける癖をつけましょう。」

生徒

「はい!あと、currentの後にハテナ(?.)を付けてアクセスする方法も便利だなと思いました。nullチェックを一行で書けるんですね。」

先生

「そう、オプショナルチェイニングですね。TypeScriptでは初期値がnullである以上、要素が存在しない可能性を常に考慮しなければなりません。ハテナを使うことで、コードを短く保ちつつ安全にプロパティにアクセスできるようになります。」

生徒

「なるほど。ところで、useRefで値を保存するときに、いつその値が書き換わったのかを画面に表示させることはできないんですか?」

先生

「いい質問です。そこがuseRefとuseStateの決定的な違いです。useRefの値を書き換えても画面は再描画されません。もし画面に反映させたいならuseStateを、裏側でこっそり値を保持したいならuseRefを選んでください。これがReactの設計思想の肝になります。」

生徒

「『裏側でこっそり』ですね!使い分けの基準がよく分かりました。まずはフォームの自動フォーカス機能から自作のコンポーネントに組み込んでみようと思います!」

先生

「その意気です。実際に手を動かしてコードを書くことで、型の知識が血肉になります。何かわからないことがあれば、またいつでも聞いてくださいね。応援していますよ!」

カテゴリの一覧へ
新着記事
New1
React
Reactでファイルアップロードを実装する方法を解説!Fetch APIで画像やPDFを送る仕組みを初心者向けに紹介
New2
React
Reactのリストとkeyをやさしく解説!初心者でもわかるリストアイテムをコンポーネントに分割する方法
New3
React
React RouterのuseNavigateフックの使い方を完全解説!初心者でもわかるプログラム的なページ遷移
New4
React
Reactでよくある型エラーと解決法をやさしく解説!初心者でも安心できる型安全な考え方
人気記事
No.1
Java&Spring記事人気No1
React
Reactとは?初心者でもわかるReact.jsの基本概念と特徴をやさしく解説
No.2
Java&Spring記事人気No2
React
React Context APIのデバッグ方法を完全解説!React DevToolsで中身を丸見えにする方法
No.3
Java&Spring記事人気No3
React
React Routerとは?シングルページアプリのルーティングを初心者向けにわかりやすく解説
No.4
Java&Spring記事人気No4
React
ReactとTypeScriptの環境構築をやさしく解説!Viteとtsconfigの設定も丁寧に紹介
No.5
Java&Spring記事人気No5
React
Reactの学習ロードマップ!初心者が最短で習得する流れを完全ガイド
No.6
Java&Spring記事人気No6
React
Reactでファイルアップロードを実装する方法を解説!Fetch APIで画像やPDFを送る仕組みを初心者向けに紹介
No.7
Java&Spring記事人気No7
React
create-react-appでReactプロジェクトを作成する手順を初心者向けに完全解説!
No.8
Java&Spring記事人気No8
React
React開発におすすめのVSCode拡張機能まとめ!初心者でもすぐ使える便利ツール紹介