制御されたinput
入力欄の値はどこにあるのか
素の HTML では、入力された文字は input 要素の中に貯まります。値を知りたければ document.querySelector("#name").value と、要素に聞きに行きました。
React ではこのやり方をとりません。画面は state から作る、というのが React の考え方だからです。入力欄の中身も state に置き、input には「state の値を映せ」と指示します。この形を 制御されたコンポーネント と呼びます。制御しているのは React だ、という意味です。
value と onChange の 2 つで 1 組
import { useState } from "react";
export default function App() {
const [name, setName] = useState("");
return (
<input
id="name"
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
);
}流れは一方通行です。まず value={name} で、入力欄には常に state の中身が映ります。次にキーを打つと onChange が呼ばれ、e.target.value つまり打ったあとの文字列で state を更新します。state が変われば画面が描き直され、input に新しい値が映ります。
打つ、state が変わる、映る。この 1 周が毎回まわっているだけです。
どちらか片方だと壊れる
value だけ書いて onChange を書かないと、何を打っても state は変わりません。state が変わらないので画面も変わらず、入力欄は最初の値のまま固まります。読み取り専用の欄になってしまうわけです。
逆に onChange だけ書いて value を書かないと、state は正しく更新されますが、入力欄の表示は入力欄が勝手に持っている値のままです。ふだんは同じに見えるので気付きませんが、送信後に state を空にしても入力欄の文字が消えない、といった形で食い違いが表に出ます。
value と onChange は 2 つで 1 組と覚えてください。
初期値は空文字にする
useState() と書くと初期値が undefined になり、React が「制御されていない欄が途中で制御された欄に変わった」と警告を出します。文字を入れる欄なら useState("") と、空文字から始めます。
演習
お問い合わせフォームのお名前欄を、state と同期させます。