React · LEARN AT YOUR OWN PACE今日も、一歩ずつ。

LESSON 09 · 約25分

refで、DOMへ必要な操作をする

再描画に使うstateと、DOM参照などを保つrefの役割を分けます。

コードを試す前に

01のVite reactテンプレート(JavaScript/JSX)を使います。特記のないApp.jsxは、そのレッスンだけで動く独立した例です。例同士を連結しないでください。

短い学習用の例です。各App.jsxは独立した例で、順に追記して一つの完成品にする形式ではありません。ファイル名、依存関係、未定義部分の前提は注記に記載します。問題内の抜粋や空欄は、そのまま実行するための完成コードではありません。

開発環境の準備を確認する →

このレッスンでわかること

  • ref経由で入力へフォーカスできる
  • refの更新だけでは再描画されないと説明できる

refは表示以外の値を覚える

useRefはcurrentというプロパティを持つオブジェクトを返し、再描画をまたいで保持します。currentを変更しても、それ自体では再描画が起きません。画面に表示するカウントや入力内容はstate、タイマーIDやDOMへの参照はrefという使い分けから始めます。

DOM操作は必要な範囲だけ

inputへrefを渡すと、DOMが配置された後でcurrentから入力要素を参照できます。ボタンのイベントでfocus()を呼べば、入力へ移動できます。Reactが管理する子要素をremoveしたりinnerHTMLで作り直したりすると、Reactの状態とDOMが食い違います。

フォーカスも利用者の流れに合わせる

ページを開くたびに突然フォーカスを奪うより、利用者が「入力へ移動」を選んだときに動かすほうが意図を伝えやすい場合があります。DOMがまだない・すでに消えた状態にも備え、current?.focus()のようにnullを扱います。

ボタンから入力へ移動する

src/App.jsx
import { useRef, useState } from 'react';

export default function App() {
  const inputRef = useRef(null);
  const [title, setTitle] = useState('');

  return (
    <main>
      <h1>次のテーマ</h1>
      <button type="button" onClick={() => inputRef.current?.focus()}>
        テーマ入力へ移動
      </button>
      <label>テーマ
        <input ref={inputRef} value={title}
          onChange={event => setTitle(event.target.value)} />
      </label>
      <p>入力中: {title || '未入力'}</p>
    </main>
  );
}

inputRefはDOM操作、titleは画面表示を担当します。refを読むのはクリック時です。

TRY IT YOURSELF

入力へフォーカスを移す

  1. 移動ボタンをマウスとキーボードの両方で押し、入力へフォーカスが移ることを確認する
  2. 「消して入力へ戻る」ボタンを追加し、setTitleとfocusをイベントで実行する
  3. 表示を変える値をrefへ置き換えると何が不足するか説明する

できたらOK:入力値はstateで描画され、ボタン操作時だけrefでフォーカスを移せる

QUICK CHECK

理解を確かめよう

ボタンを押したら入力欄へフォーカスを移したい。適切なのはどれ?

公式資料でもう少し詳しく

ここまで読めたら、ひとつ前進。