Kodokon kodokon.com

制御されたフォーム

すべてのフォームフィールドを React の state から制御する方法を学び、信頼できるデータを検証して送信できるようにします。

8 分 · 3 問

このレッスンを Kodokon で開く

React では、すべてのフィールドが制御された状態になると、フォームは予測可能になります。表示される値はコンポーネントの state に由来し、キー入力のたびに onChange を通ってその state を更新します。もはや DOM が信頼できる情報源ではなく、あなたの state がそうなります。実際には、value プロパティを state 変数にバインドし、更新関数を呼び出すハンドラーを用意します。

JSX
import { useState } from "react";

function EmailField() {
  const [email, setEmail] = useState("");

  return (
    <input
      type="email"
      value={email}
      onChange={(e) => setEmail(e.target.value)}
    />
  );
}
制御されたフィールド: value が state を読み取り、onChange がそれを書き込みます。

実際のフォームに単一のフィールドしかないことはめったにありません。useState の呼び出しを積み重ねるのではなく、値を 1 つのオブジェクトにまとめ、汎用ハンドラーを書きましょう。各フィールドの name 属性は、オブジェクトのキーと正確に一致していなければなりません。それこそが、どのプロパティを更新するかをハンドラーに伝えるものです。

JSX
const [form, setForm] = useState({
  username: "",
  password: "",
});

function handleChange(e) {
  const { name, value } = e.target;
  setForm((prev) => ({ ...prev, [name]: value }));
}
フォーム内のすべてのフィールドを 1 つのハンドラーで処理します。

残るは送信です。デフォルトでは、フォームが送信されるとブラウザはページを再読み込みします。onSubmit ハンドラーの先頭で e.preventDefault() を呼び出しましょう。また、フォーム全体の state がすでに手元にあるため、そこは送信前にデータを検証するのに適した場所でもあります。

JSX
function handleSubmit(e) {
  e.preventDefault();
  if (form.username.trim() === "") {
    alert("Username is required.");
    return;
  }
  console.log("Submitting:", form);
}

return (
  <form onSubmit={handleSubmit}>
    <input
      name="username"
      value={form.username}
      onChange={handleChange}
    />
    <button type="submit">Create account</button>
  </form>
);
ページを再読み込みせずに、検証してから送信します。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. React において、制御されたフィールドとは何によって定義されますか?
    • その値が DOM に保存され、ref で読み取られる
    • その値が state に由来し、キー入力のたびに onChange を通る
    • フォームが送信されるまで読み取り専用である
    • 入力したデータを自動的に検証する
  2. <input>value={email} を渡し、onChange を用意しなかった場合、何が起こりますか?
    • フィールドが固まる: 入力しても何も反応しなくなる
    • フィールドは正常に動作し、React が自分で入力を処理する
    • 最初のレンダリングでコンポーネントがクラッシュする
  3. onSubmit ハンドラー内の e.preventDefault() は何のためにありますか?
    • ネイティブのフォーム送信によって引き起こされるページの再読み込みを防ぐため
    • フォームのフィールドを自動的にクリアするため
    • イベントが親コンポーネントへ伝播するのを止めるため
    • ブラウザの HTML 検証を無効にするため