はじめに
以前紹介した第3弾では、「Props」と「配列のmap処理」を使って、データを外から渡して画面を組み立てる方法を学びました。
しかし、これまでの画面は一度表示されたらそのままの「静的」なものでした。Webアプリの醍醐味は、ユーザーがボタンを押したり文字を入力したりすると、それに反応して画面が切り替わることですよね。
そこで第4弾の今回は、Reactの心臓部とも言える「useState(状態管理)」と「フォーム入力」を解説します! テキストボックスに入力した文字が、リアルタイムで画面に反映される「リアルタイムプレビュー機能」を体感していきます。
1. そもそも「State」って何?
State(ステート)を直訳すると「状態」です。 ReactにおけるStateとは、「画面に表示するためのデータを覚えておく、特別な変数」のことです。
Pythonや通常のJavaScriptの変数(let name = “名前”)との最大の違いは、「値が更新されたとき、Reactが自動的に画面を再描画(レンダリング)してくれる」という点です。
この機能を使うために、Reactに用意されているのが useState という仕組み(フック)です。
2. リアルタイム・プロフィール編集画面を作ろう
さっそく、名前などを入力すると、リアルタイムプレビューが表示され、プロフィールカードを追加できるコンポーネントを作ってみましょう。
前回までの記事のコードをさらにuseStateを使って進化させます。
デザインには Tailwind CSS を使用しています。
import { useState } from 'react'
import Header from './Header'
import ProfileCard from './ProfileCard'
import CounterButton from './CounterButton'
import './App.css'
function App() {
// 1. 配列データを useState で管理
const [members, setMembers] = useState([
{
id: 1,
avatar: '🚀',
name: 'React a',
bio: 'フロントエンド開発を勉強中のエンジニアです!',
},
{
id: 2,
avatar: '🎨',
name: 'デザイン b',
bio: 'UI/UXデザインが得意です。最近CSSアニメーションにハマっています。',
},
{
id: 3,
avatar: '⚽',
name: 'スポーツ c',
bio: '休日はサッカーと筋トレ!Web開発でスポーツアプリを作りたいです。',
},
])
// 2. フォームの入力値を保持する State(プレビュー用にもそのまま使われます!)
const [avatar, setAvatar] = useState('')
const [name, setName] = useState('')
const [bio, setBio] = useState('')
// 3. カードを追加する処理
const handleAddMember = (e) => {
e.preventDefault()
if (!name.trim()) return
const newMember = {
id: Date.now(),
avatar: avatar || '👤',
name: name,
bio: bio,
}
setMembers([...members, newMember])
// 送信後に入力欄とプレビューをリセット
setAvatar('')
setName('')
setBio('')
}
return (
<div className="app-container">
<Header />
<main className="main-content">
{/* カード追加フォーム */}
<form className="add-member-form" onSubmit={handleAddMember}>
<h3>新しいメンバーを追加</h3>
<div className="form-group">
<input
type="text"
placeholder="アイコン (例: 🏀)"
value={avatar}
onChange={(e) => setAvatar(e.target.value)}
/>
<input
type="text"
placeholder="名前"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input
type="text"
placeholder="自己紹介"
value={bio}
onChange={(e) => setBio(e.target.value)}
/>
</div>
{/* 「リアルタイムプレビュー」領域 */}
<div className="preview-container">
<p className="preview-title"> 完成イメージ(プレビュー)</p>
{/* ボタンを押す前でも、State (avatar, name, bio) の変化が即座に反映される */}
<ProfileCard
avatar={avatar || '❓'}
name={name || '(名前を入力中...)'}
bio={bio || '(自己紹介を入力中...)'}
/>
</div>
<button type="submit" className="add-button">
この内容でカードを追加する
</button>
</form>
{/* 確定したメンバー一覧 */}
<div className="card-list">
<h3>メンバー一覧</h3>
{members.map((member) => (
<ProfileCard
key={member.id}
avatar={member.avatar}
name={member.name}
bio={member.bio}
/>
))}
</div>
<CounterButton />
</main>
</div>
)
}
export default App3. コードの解説
useState の書き方
// 2. フォームの入力値を保持する State
const [avatar, setAvatar] = useState('')
const [name, setName] = useState('')
const [bio, setBio] = useState('')この部分は、Reactでフォーム(テキスト入力欄)を扱う際の最重要ポイントです!
なぜこのように useState を3つ並べて書いているのか、初心者向けに3つのステップで徹底解説します。
一言でいうと「キーボード入力のメモ帳」
この3行は、ユーザーがキーボードで文字を打ち込んだときに、「今、それぞれの入力欄に何の文字が入っているか」を一時的に記憶しておくためのメモ帳(State) を3個用意しています。
- avatar ➔ アイコン用入力欄のメモ帳(初期値:
''空文字) - name ➔ 名前用入力欄のメモ帳(初期値:
''空文字) - bio ➔ 自己紹介用入力欄のメモ帳(初期値:
''空文字)
入力欄(<input>)とStateの仕組み
入力欄のHTML部分を見てみましょう。
<input
type="text"
placeholder="名前"
value={name} // メモ帳(State)の中身を表示する
onChange={(e) => setName(e.target.value)} // キーボードが叩かれたらメモ帳を更新する
/>ここで行われている「二人三脚」の動き(専門用語で双方向バインディング)は以下の通りです。
【ユーザーの操作】
ユーザーが「あ」と入力する
│
▼
【onChange が発動】
`e.target.value`(=「あ」)を拾って `setName('あ')` を実行!
│
▼
【State が更新される】
`name` の中身が `''` から `'あ'` に変わる
│
▼
【React が画面を再描画】
`value={name}` によって、入力欄に「あ」が表示される!一瞬でこのループが回るため、「キーボードを打つ ➔ 即座にStateに保存される」 という状態が作られます。
もし useState で管理しなかったらどうなる?
ユーザー目線ではただの <input> タグでも文字は打ち込めます。
では、「なぜわざわざ onChange で毎回 State を書き換えるのか?」「ボタンを押した時に <input> タグから文字を読み取る方法(従来のHTML/JS)と何が違うのか?」
その違いとReactの仕組みを、3つの理由でスッキリ解説します!
違い1:入力欄を「空(リセット)」にできるかどうか
ボタンを押したあと、入力欄の文字を「消して空にする」動きを想像してみてください。
- 従来の書き方(inputを後から読む方法)
ボタンが押された後、JavaScriptでわざわざ document.getElementById(‘name-input’).value = ” のように、HTMLの要素を直接操作して消すコードを書く必要があります。
- Reactの書き方(value={name} + onChange)
State(name)を入力欄とガッチリ紐づけているため、ボタンを押した後の処理で setName(”)(Stateを空にする)を実行するだけ で、入力欄の文字が勝手に消えてリセットされます!
Reactの基本理念: 「画面(HTML)を直接触って操作する」のではなく、「データ(State)を変えれば、画面が勝手に追従する」 という設計になっているためです。
違い2:「ボタンを押す前」に入力チェックや制御ができる
onChange で常に最新の文字を React が把握(監視)していると、以下のような高度な機能がボタンを押す前(入力中)に簡単に作れるようになります。
- リアルタイム入力チェック: 「名前は10文字以内で入力してください」という警告を入力中にすぐ出せる。
- ボタンの有効/無効切り替え: 「名前が空のときは、追加ボタンを押せない(グレーアウト)ようにする」(例:<button disabled={!name}>)。
- リアルタイムプレビュー: 第4弾の冒頭で触れたように、入力した文字がカードを追加する前にプレビュー画面に即座に反映される。
もし「ボタンを押した時にだけ input を読む」方法だと、入力中のリアルタイムな変化に対応できません。
違い3:画面全体の整合性をReactが完璧に管理できる
通常のJavaScriptで「ボタンが押されたら <input> の値を読んで、DOM(HTML)を生成して appendChild で追加する…」という処理を書くと、コードが複雑になり、バグ(画面の表示崩れやデータのズレ)が起きやすくなります。
Reactでは、以下のシンプルな1方向のデータルールだけで動いています。
【ユーザーの操作】
キーボードを叩く / ボタンを押す
│
▼
【State(データ)の更新】
`setName(...)` や `setMembers(...)` でデータを変える
│
▼
【Reactの自動描画】
データに合わせて、画面全体を自動で正しく描き直す!入力欄の文字(name)も、カードのリスト(members)も、すべてデータ(State)としてReactの管理下に置いておくことで、アプリ全体の動きが予測可能になり、安全に動くようになります。
リアルタイムプレビューの仕組み
次に「プレビュー画面(リアルタイム反映)」とは具体的にどこに作れて、どう動くのかを詳しく解説します。
以下のコードの部分です。
return (
<div className="app-container">
<Header />
<main className="main-content">
{/* 1. 入力フォーム */}
<form onSubmit={handleAddMember}>
<input value={avatar} onChange={(e) => setAvatar(e.target.value)} />
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={bio} onChange={(e) => setBio(e.target.value)} />
{/* 2. 👁️ リアルタイムプレビュー画面!! */}
{/* ボタンを押す前でも、State (nameやbio) の文字がそのまま映し出される */}
<div className="preview-area">
<p>👇 完成イメージ(プレビュー)</p>
<ProfileCard
avatar={avatar || '❓'} // 空なら「❓」を表示
name={name || '(名前を入力中...)'}
bio={bio || '(自己紹介を入力中...)'}
/>
</div>
{/* 3. 追加ボタン */}
<button type="submit">この内容でカードを追加する</button>
</form>
{/* 4. ボタンを押して確定したカード一覧 */}
<div className="card-list">
{members.map((member) => (
<ProfileCard key={member.id} {...member} />
))}
</div>
</main>
</div>
)
1. プレビュー画面ってどこに作れるの?
フォーム(入力欄)とカード一覧(ボタンを押して増える場所)の**「間」**に、入力中の文字がそのまま映し出される「お試しカード」を1枚置くイメージです。
2. なぜ「ボタンを押す前」に動くの?
ここが React(useState)の最大の面白さです!
- キーボードで文字を打つ:onChange が発動して、State(name や bio)の中身が更新される。
- Reactが即座に画面を描き直す:<ProfileCard bio=”{bio}” name=”{name}”/> の部分に最新のStateの値がそのまま流れ込むため、キーボードを叩くたびにプレビュー画面のカードがパッパッとリアルタイムで書き換わります!
- 「追加ボタン」を押す:入力欄とプレビューで確認して「これでOK!」となったタイミングでボタンを押すと、<form onSubmit={handleAddMember}> の handleAddMember 関数が実行されて、その内容が members 配列(確定リスト)に追加されます。
4.まとめ
今回の仕組みでは、 2パターンのState が組み合わさっています。
- 入力中の State(avatar, name, bio):ボタンを押さなくても、キーボードを叩くだけで一瞬で変わる。「プレビュー表示」 や 「入力欄の文字」 を動かすために使う。
- 確定後の State(members 配列):「追加ボタン」を押した瞬間だけ 変わる。「下に並ぶカードのリスト」 を増やすために使う。
「入力中の文字」まで State で管理しているからこそ、このような**「ボタンを押す前に完成形を目で確認できる(プレビュー)」**という機能を使うことができます。
昔のJavaScript(DOM操作)だと、要素を取得してテキストを書き換えて…と面倒な処理が必要でしたが、Reactなら「Stateを更新するだけ」で画面が勝手についてきてくれます。
次回・第5弾では、今回の知識をさらに発展させて、「配列のState管理(ToDoリストのようにデータを追加・削除する動き)」に挑戦します。


コメント