zukucode
主にWEB関連の情報を技術メモとして発信しています。

React useRefで入力欄にフォーカスを当てる

入力フォームを開いた直後や、入力エラーが出たときに、特定の入力欄へフォーカスしたいことがあります。DOMの要素自体を参照するにはuseRefを使います。

入力欄を参照する

import { useRef, useState } from 'react';

export const ItemForm = () => {
  const inputRef = useRef<HTMLInputElement>(null);
  const [name, setName] = useState('');
  const [message, setMessage] = useState('');

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!name.trim()) {
      setMessage('名前を入力してください。');
      inputRef.current?.focus();
      return;
    }
    setMessage(`追加しました: ${name.trim()}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="item-name">名前</label>
      <input
        id="item-name"
        ref={inputRef}
        value={name}
        onChange={(event) => setName(event.target.value)}
        aria-describedby="item-message"
      />
      <button type="submit">追加</button>
      <p id="item-message" role="status">{message}</p>
    </form>
  );
};

currentは初回描画中などにnullになり得るので、?.focus()で確認します。ボタンを押して空欄なら、メッセージを表示し、入力欄へフォーカスが戻ります。

stateとrefの違い

入力値は画面表示に使うためuseStateで管理します。一方、DOMへの参照は描画内容そのものではないためuseRefに置きます。ref.currentを書き換えても再描画は起きません。

表示後にフォーカスしたい場合

条件付きで入力欄を表示する場合、表示する前にfocus()しても対象要素はありません。表示後にEffectを実行するか、用途に合えばautoFocusを検討します。モーダルではフォーカスを開く前の要素へ戻すことも含めて設計してください。

ページ読み込み直後に意図せずフォーカスを移すと、キーボード操作やスクリーンリーダーの利用者を混乱させることがあります。明確な操作の結果として必要な場合に使います。


関連記事

  • TypeScript i18nextの動的な翻訳キーを抽出対象に含める

    i18nextでステータスに応じた文言を表示する場合、翻訳キーを動的に切り替えることがあります。ただし、実行時に正しく表示できることと、翻訳キーの抽出ツールが使用箇所を検出できることは別です。今回は、...


  • React useStateで入力フォームを作成する

    Reactでテキストボックスに入力した値を使用するには、useStateで値を保持します。今回は名前とメールアドレスを入力し、送信ボタンを押すと入力内容を表示するフォームを作成します。この例では入力値...


  • React useStateで一覧の追加と削除を行う

    Reactで一覧を表示するときは、配列をuseStateへ保存できます。今回は簡単な買い物リストを作り、項目の追加と削除を行います。配列のpushやspliceで既存のstateを直接変更するのではな...


  • React useEffectで無限ループが発生するときに確認すること

    ReactのuseEffectを利用したときに無限ループが発生してしまうことがあります。特に注意したいのが、ESLintのreact-hooks/exhaustive-depsで表示された警告をUpd...


  • React useEffectの後片付けでイベント登録を解除する

    画面の幅が変わったときに表示を更新したい場合、ブラウザのresizeイベントを登録できます。登録したままにすると、コンポーネントが不要になったあとも処理が残るため、useEffectの後片付けを用意し...


  • React 関数コンポーネントにプロパティを設定する

    React+TypeScriptで作成した関数コンポーネントにプロパティを設定する方法を紹介します。以下は送信ボタンのコンポーネントを作成しています。isSubmittingというプロパティを用意して...


  • Reactで兄弟コンポーネントの状態を共有する

    検索欄に入力した文字列を、別の一覧コンポーネントでも使いたい場合があります。兄弟同士で別々にstateを持つと値がずれるため、共通の親にstateを置きます。入力欄は値を受け取り、変更を親へ通知します...


  • React useStateでselectの選択値を取得する

    Reactでプルダウンの選択値を扱うには、selectのvalueとonChangeを使用します。DOMから取得するvalueは、数値の選択肢を表示していても文字列です。選択値をそのまま識別子として扱...


  • React react-router-domの基本的な使い方

    React+TypeScriptのプロジェクトにreact-router-domを導入してSPAのアプリケーションを作成する方法を紹介します。まずはreact-router-domのパッケージをインス...


  • react-router-dom ページごとにファイルを分割する

    react-router-domでシングルアプリケーションを作成していると、ページ数が増えるにしたがって作成されるjsファイルのファイルサイズもどんどん増えていきます。ページごとにファイルを分割し、そ...