制御された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 と同期させます。

ヒント

App.jsx
App.jsx
プレビュー

できているか

  • お名前の入力欄が画面にある
  • 「あおい」と入力するとあいさつ文が「こんにちは、あおい さん」になる
  • 「そら」に打ち直すとあいさつ文も「そら」に変わる