R初めてのReact

Day 3リスト・条件・フォーム — 実データを画面に出す

制御コンポーネント(フォームの値を React が握る)

input の value を state に結びつけ、onChange で更新する制御コンポーネントの型を身につける。

入力欄の値を React の state で管理する

フォームの入力欄(input など)は、放っておくとブラウザ側が値を持ちます。React ではこれを「state に値を持たせ、input はその state を映すだけ」に変えるのが定番です。こうすると入力値の唯一の正解が state になり、React がフォームを握れます。この形を制御コンポーネントと呼びます。

作り方は2ステップです。1つ目、input の value に state を渡す(表示は常に state に従う)。2つ目、onChange で入力のたびに setState して state を更新する。これで「state → 表示」「入力 → state」が一周し、常に一致します。

TSX
import { useState } from "react";

function NameForm() {
  const [name, setName] = useState("");

  return (
    <input
      value={name}
      onChange={(e) => setName(e.target.value)}
    />
  );
}
value に state を渡し、onChange で state を更新する(制御コンポーネントの基本形)

onChange に渡す関数は、イベント e を受け取ります。入力された今の文字列は e.target.value で取れます。これを setName に渡すと state が更新され、再描画で value={name} が新しい値になり、画面に反映されます。

なぜ React に値を握らせるのか

値が state にあると、送信前の入力チェック、他の欄と連動した表示、ボタンの有効・無効の切り替え、入力のリセットなどが、すべて state を見る・書き換えるだけで実現できます。値がブラウザ任せだと「今いくつ入っているか」を毎回取りに行く必要があり、ロジックが散らかります。state に一本化することで扱いやすくなります。

非制御(値をブラウザが持つ)

value を state に結ばず、必要なときに DOM から読み出す

TSX
// React は値を把握していない
<input ref={inputRef} />
// 送信時に inputRef.current.value を取りに行く

制御(値を React が持つ)

value を state に結び、常に state が唯一の正解

TSX
<input
  value={name}
  onChange={(e) => setName(e.target.value)}
/>

フォームの送信も押さえておきます。<form> の onSubmit で送信を受け取りますが、そのままだとブラウザがページを再読み込みしてしまいます。これを止めるのが e.preventDefault() です。止めた上で、state に入っている値を使って処理します。

TSX
function SearchForm() {
  const [keyword, setKeyword] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault(); // ページ再読み込みを止める
    console.log("検索:", keyword);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={keyword}
        onChange={(e) => setKeyword(e.target.value)}
      />
      <button type="submit">検索</button>
    </form>
  );
}
onSubmit で受け取り、preventDefault で再読み込みを止めてから state の値を使う
  1. state を用意する(useState で入力値を持つ)
  2. input の value に state を渡す(表示は state に従う)
  3. onChange で e.target.value を setState して更新する
  4. 送信は onSubmit で受け、先頭で e.preventDefault() を呼ぶ

value を渡すなら onChange も必ず付ける

value={name} だけ書いて onChange を付けないと、値が state に固定されて何を打っても変わらない「読み取り専用」になり、React が警告します。制御コンポーネントでは value と onChange は必ずセットにします。

AIにはこう聞く

「名前とメールを入力する制御コンポーネントのフォームを作って。各 input は value を state に結び、onChange で更新。送信は onSubmit で preventDefault してから値をまとめてログに出して」と伝えると、この章の型どおりのコードが返ります。

読んでも腑に落ちない所は、AIに噛み砕いてもらいましょう。

理解度チェック

答えられれば、面接で説明できる状態に一歩近づきます。

Q1

制御コンポーネントで input を作るとき、value と一緒に必ず用意すべきものはどれ?

Q2

onChange のハンドラで、入力された今の文字列を取り出すのはどれ?

Q3

「非制御コンポーネント」と「制御コンポーネント」の違いを、値をどこが持つかに注目して説明してください。

記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。