このテーマのゴール
ここで目指すのは、「入力欄に打ち込んだ文字が、そのままリアルタイムで画面に表示されるコンポーネント」を自分で作れるようになることです。
これは一見シンプルですが、React でフォームを扱うときの超重要パターン
「入力値を state で管理する(=制御されたコンポーネント)」 をそのまま体験できます。
入力欄に文字を打つ
→ state が更新される
→ 画面の表示が自動で変わる
この流れを、ちゃんとつかみにいきましょう。
完成イメージのコード
入力した文字をそのまま表示するコンポーネント
"use client";
import { useState } from "react";
export function EchoInput() {
const [text, setText] = useState("");
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
setText(event.target.value);
}
return (
<div
style={{
padding: "16px",
border: "1px solid #e5e7eb",
borderRadius: "8px",
maxWidth: "400px",
}}
>
<label style={{ display: "block", marginBottom: "8px", fontSize: "14px" }}>
文字を入力してください:
</label>
<input
type="text"
value={text}
onChange={handleChange}
placeholder="ここに入力すると下に表示されます"
style={{
width: "100%",
padding: "6px 8px",
borderRadius: "4px",
border: "1px solid #d1d5db",
marginBottom: "12px",
}}
/>
<p style={{ fontSize: "14px", color: "#374151" }}>
現在の入力:<strong>{text || "(まだ何も入力されていません)"}</strong>
</p>
</div>
);
}
TSXページ側はこんな感じで使います。
import { EchoInput } from "./EchoInput";
export default function Page() {
return (
<main style={{ padding: "24px", fontFamily: "system-ui, sans-serif" }}>
<h1 style={{ fontSize: "22px", marginBottom: "16px" }}>
入力をリアルタイム表示するフォーム
</h1>
<EchoInput />
</main>
);
}
TSX入力欄に文字を打つと、その下の「現在の入力:〜」の部分が、
打った瞬間にどんどん変わっていきます。
useState で「今の入力値」を覚えておく
なぜ state が必要なのか
この行が心臓部です。
const [text, setText] = useState("");
TSXここでやっていることをかみ砕くと、
textは「今、入力欄に入っている文字」を表す値setTextは「text を新しい文字列に更新するための関数」useState("")は「最初は空文字(何も入力されていない状態)からスタートする」という意味
つまり、
- 最初は
text = "" - ユーザーが何か入力するたびに
setText("入力された文字")が呼ばれる textが変わるたびに React が画面を描き直してくれる
という仕組みになっています。
ここで重要なのは、「入力欄の中身を React の state で“持つ”」という発想です。
これを「制御されたコンポーネント(controlled component)」と呼びます。
input と state を「双方向につなぐ」
value と onChange のセットが超重要
フォーム入力を React で扱うときの基本パターンは、この 2 つです。
<input
type="text"
value={text}
onChange={handleChange}
/>
TSXvalue={text}
→ 「この input の中身は、常に text の値ですよ」と React に伝える
onChange={handleChange}
→ 「ユーザーが入力を変えたら、handleChange を呼んでね」と React に伝える
この 2 つがセットになることで、
ユーザーが文字を打つ
→ onChange が発火
→ handleChange の中で setText(…) が呼ばれる
→ text の値が変わる
→ value={text} の部分が更新され、input の表示も変わる
という「双方向のつながり」が生まれます。
handleChange の中で何をしているか
handleChange の中身を見てみましょう。
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
setText(event.target.value);
}
TSXここでやっていることはシンプルで、
event.targetは「このイベントが起きた input 要素」event.target.valueは「その input に今入っている文字列」- それをそのまま
setTextに渡している
というだけです。
つまり、「ユーザーが入力した内容を、そのまま state に保存している」状態です。
JSX の中で state をそのまま表示する
「今の入力」を画面に映す
表示部分はこうなっています。
<p>
現在の入力:<strong>{text || "(まだ何も入力されていません)"}</strong>
</p>
TSXここでのポイントは 2 つです。
{text}
→ state の値をそのまま画面に埋め込んでいる
text || "(まだ何も入力されていません)"
→ text が空文字のときだけ、代わりのメッセージを表示している
これにより、
- 何も入力していないとき
→ 「(まだ何も入力されていません)」と表示 - 「こんにちは」と入力したとき
→ 「現在の入力:こんにちは」と表示
という、分かりやすい UI になります。
ここであなたがやっているのは「text を変えること」だけ。
「表示を更新する」処理は、全部 React が勝手にやってくれます。
まとめ:このフォームコンポーネントでつかんでほしいこと
この「入力した文字をリアルタイム表示するコンポーネント」で、絶対に押さえてほしいのはこの感覚です。
入力欄の中身も「state」として React に持たせる(制御されたコンポーネント)value と onChange をセットで使うことで、「input ↔ state」がつながる
state が変わると、React が自動で画面を描き直してくれるので、自分で DOM をいじる必要はない
ここが腑に落ちると、
検索ボックス
コメント入力フォーム
プロフィール編集フォーム
みたいな「ユーザーの入力を扱う UI」を、React らしい書き方で組めるようになります。
もし余力があれば、このコンポーネントに「文字数カウンター(例:text.length)」を追加してみてください。
「1つの state から、複数の表示(入力内容+文字数)を派生させる」感覚が、さらに深くつかめます。
