🐥

Reactのフォーム更新はどう動く?e.target → 分割代入 → スプレッド構文の流れ

に公開
2025/11/26

React でフォームを扱うとき、よく次のようなコードが登場します。

const onChange = (e) => {
  const { name, value } = e.target;
  setForm((f) => ({ ...f, [name]: value }));
};

「これはどう動いているの?」
「なぜ1つの関数で複数の input を処理できるの?」
そんな疑問を、e.target → 分割代入 → スプレッド構文 の順番でわかりやすく解説


1. e.target の正体:HTMLInputElement(オブジェクト)

フォーム入力で onChange が発火すると、イベントオブジェクト e が渡されます。
その e.target は、イベントを起こした input 要素そのもの。

<input name="username" value="kato" placeholder="ユーザー名">
//これを入力すると、e.target の中身は以下のような オブジェクト です。
HTMLInputElement {
  value: "kato",
  name: "username",
  type: "text",
  placeholder: "ユーザー名",
  ...
}

注:HTMLタグの見た目をしているが、正体はオブジェクトです。
ブラウザは内部で HTML を DOM(オブジェクト)に変換し、その上で表示時にタグの形にレンダリングしています。


2. 分割代入で必要な値だけ取り出す

e.target には大量の情報があります。そこで必要なものだけ取り出すために、分割代入を使います👇

const { name, value } = e.target;
//これは次と同じ意味です:
const name = e.target.name;
const value = e.target.value;

これで、

  • name → input の name 属性
  • value → 入力された値
    の2つの単独変数を取得できます。

3. setForm の中身:スプレッド構文でオブジェクトを更新

setForm((f) => ({ ...f, [name]: value }));

(1) ...f で既存の form オブジェクトを展開

たとえば現在の state が:

f = {
  username: "",
  userId: "",
  password: ""
}

という状態だとします。
{ ...f } はこれを展開して同じものを作るだけです。


(2) [name]: value で動的にキーを上書き

// name の中身が "username" なら:
{ ...f, username: "kato" }
// name が "password" なら:
{ ...f, password: "xxx" }

というように、
どの input が変更されたかによって更新するプロパティを自動的に切り替えられます。


4. 1つの onChange で複数 input を管理できる理由

name 属性を使って “どの項目が変更されたか” を識別できるから
React では、同じ onChange 関数をどの input に渡しても問題ありません。

<input name="username" onChange={onChange} />
<input name="userId" onChange={onChange} />
<input name="password" onChange={onChange} />

input が変わるたびに:

  • e.target.name に変わった input の名前が入る
  • e.target.value に入力値が入る
  • setForm({ ...f, [name]: value }) が適切なキーを更新
    という仕組みになっています。

5. 最終まとめ

✅ HTML の input は実体として HTMLInputElement というオブジェクト
✅ e.target はそのオブジェクト
✅ 分割代入で name と value を取り出す
✅ スプレッド構文で既存の state を展開
✅ [name]: value で動的にキーを更新
✅ だから1つの onChange で複数の input を扱える


6. 完成コード

export default function App() {
  const [form, setForm] = useState({
    username: "",
    userId: "",
    password: "",
  });

  const onChange = (e) => {
    const { name, value } = e.target;
    setForm((f) => ({ ...f, [name]: value }));
  };

  return (
    <form>
      <input name="username" value={form.username} onChange={onChange} />
      <input name="userId" value={form.userId} onChange={onChange} />
      <input name="password" value={form.password} onChange={onChange} />
    </form>
  );
}

Discussion