- DAY 19:State更新 前半 ― 「いろいろな値を安全に更新する」感覚を身につける
- 数値State ― カウンターで「足し算・引き算」を練習する
- 文字列State ― 入力フォームで「文字列の更新」を体感する
- Boolean State ― ON/OFF・表示/非表示を切り替える
- 前のStateを利用する ― 「安全な更新」のための関数型更新
- State更新関数 ― 「新しい値をReactに渡す窓口」
- 数値・文字列・Booleanをまとめて扱うミニ例
- DAY 19:State更新 前半のまとめ
- DAY 19:State更新 中盤 ― 「実際のUIでState更新パターンを使い分ける」
- 数値State ― 「制限付きカウンター」で前のStateを意識する
- 文字列State ― 「入力+リセット+追記」で更新パターンを増やす
- Boolean State ― 「複数の表示を切り替える」実用的なトグル
- 前のStateを利用する ― 「連続更新」や「条件付き更新」で必須になる
- State更新関数 ― 「直接値を渡す」と「前のStateから計算する」の使い分け
- 数値・文字列・Booleanを組み合わせたミニUI
- DAY 19:State更新 中盤のまとめ
- DAY 19:State更新 後半 ― 「安全で読みやすいState更新」を習慣にする
- 数値State ― 「計算ロジックは更新関数の中に閉じ込める」
- 文字列State ― 「入力・追記・リセットをパターンとして整理する」
- Boolean State ― 「ON/OFFの意味を名前で表現する」
- 前のStateを利用する ― 「ロジックをState更新関数の中に閉じ込める」
- State更新関数 ― 「直接値を渡す」と「関数型更新」の使い分けを定着させる
- まとめ用ミニテンプレート ― 「State更新の基本形」を手元に置いておく
- DAY 19:State更新 後半のまとめ
- DAY 19:State更新 制作編 ― カウンターアプリを完成させる
- カウンターアプリのゴールイメージを決める
- 数値State ― カウンターの「現在の値」を持つ
- State更新関数 ― +1 / -1 / リセットの動きを定義する
- 文字列State ― カウンターにメッセージを添える
- Boolean State ― カウンターの「拡張機能」をON/OFFする
- カウンターアプリ完成版テンプレート
- DAY 19:カウンターアプリ制作のまとめ
DAY 19:State更新 前半 ― 「いろいろな値を安全に更新する」感覚を身につける
DAY 19では、前日までに学んだ useState を一歩進めて、Stateの更新パターンを整理していきます。 Reactでは「値をどう持つか」だけでなく、「どう安全に更新するか」がとても重要になります。
この前半では、次のポイントを扱います。
- 数値State
- 文字列State
- Boolean State
- 前のStateを利用する
- State更新関数
それぞれをステップバイステップで確認しながら、 「State更新はこう書くと安全で読みやすい」という感覚を身につけていきます。
数値State ― カウンターで「足し算・引き算」を練習する
基本の数値State更新:count + 1
まずは、いちばんシンプルな数値Stateから見ていきます。
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={() => setCount(count + 1)}>
1増やす
</button>
<button onClick={() => setCount(count - 1)}>
1減らす
</button>
</div>
);
}
export default Counter;
JSXここで起きていることを整理すると、
countは数値のStateです。setCount(count + 1)で「今の値+1」に更新しています。setCount(count - 1)で「今の値−1」に更新しています。
重要ポイント:
- 数値Stateは、「今の値をもとに新しい値を計算する」パターンが基本です。
setCount(count + 1)のように、「今のcountを使って新しい値を作る」書き方に慣れてください。
文字列State ― 入力フォームで「文字列の更新」を体感する
入力値を文字列Stateとして扱う
次に、文字列Stateの更新を見ていきます。
import { useState } from "react";
function NameInput() {
const [name, setName] = useState("");
return (
<div>
<input
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="名前を入力してください"
/>
<p>現在の入力:{name}</p>
</div>
);
}
export default NameInput;
JSXここで起きていることをステップで整理すると、
nameは文字列のStateです。setName(event.target.value)で「入力欄に今入っている文字列」に更新しています。value={name}によって、入力欄の表示は常にStateと同期しています。
重要ポイント:
- 文字列Stateは、「ユーザーの入力をそのままStateに反映する」パターンが基本です。
setName(...)の引数には、「新しい文字列」をそのまま渡します。
Boolean State ― ON/OFF・表示/非表示を切り替える
トグルスイッチでBoolean Stateを更新する
Boolean(真偽値)のStateは、ON/OFFや表示/非表示の切り替えに使われます。
import { useState } from "react";
function Toggle() {
const [isOn, setIsOn] = useState(false);
return (
<div>
<p>現在の状態:{isOn ? "ON" : "OFF"}</p>
<button onClick={() => setIsOn(!isOn)}>
切り替え
</button>
</div>
);
}
export default Toggle;
JSXここで起きていることをステップで整理すると、
isOnはBooleanのStateです(trueまたはfalse)。setIsOn(!isOn)で「今の値を反転」しています。true→falsefalse→true
- 表示は
isOn ? "ON" : "OFF"で切り替えています。
重要ポイント:
- Boolean Stateは、「今の値を反転する」更新がよく使われます。
setIsOn(!isOn)のように、「今のStateをもとに新しいStateを作る」書き方が基本です。
前のStateを利用する ― 「安全な更新」のための関数型更新
「前のStateを使う」もう一つの書き方
ここからが少し重要な話です。 Reactでは、State更新が「まとめて処理される」ことがあり、 そのときに 「前のStateを使う更新」 を安全に書くためのパターンがあります。
それが、関数型更新と呼ばれる書き方です。
setCount((prevCount) => prevCount + 1);
JSXこれは、
prevCount→ 「前のStateの値」prevCount + 1→ 新しい値
という意味になります。
カウンターを関数型更新で書き直す
先ほどのカウンターを、関数型更新で書き直してみます。
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
const handleIncrement = () => {
setCount((prevCount) => prevCount + 1);
};
const handleDecrement = () => {
setCount((prevCount) => prevCount - 1);
};
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={handleIncrement}>
1増やす
</button>
<button onClick={handleDecrement}>
1減らす
</button>
</div>
);
}
export default Counter;
JSXここで起きていることをステップで整理すると、
setCount((prevCount) => prevCount + 1);- Reactが「前の
countの値」をprevCountとして渡してくれます。 - その
prevCountをもとに新しい値を計算します。
- Reactが「前の
setCount((prevCount) => prevCount - 1);- 同じく、「前の値−1」を新しいStateとして渡します。
重要ポイント:
- 「前のStateをもとに新しいStateを計算する」場合は、関数型更新が安全です。
- 特に、同じStateを連続で更新するようなケースでは、この書き方が推奨されます。
State更新関数 ― 「新しい値をReactに渡す窓口」
更新関数は「新しいStateを渡すための関数」
setCount・setName・setIsOn などの更新関数は、
「新しいStateはこれです」とReactに渡すための窓口
です。
更新関数の使い方には、主に2パターンあります。
1. 新しい値を直接渡すパターン
setName("ゲスト");
setIsOn(true);
setCount(10);
JSX- 「前のStateは関係なく、これを新しい値にしたい」というときに使います。
2. 前のStateをもとに新しい値を計算するパターン(関数型更新)
setCount((prevCount) => prevCount + 1);
setIsOn((prevIsOn) => !prevIsOn);
JSX- 「前のStateをもとに新しい値を決めたい」というときに使います。
重要ポイント:
- 更新関数は、「新しいStateをReactに渡すための唯一の入口」です。
- 直接代入(
count = count + 1など)は絶対に使わず、必ず更新関数を通します。
数値・文字列・Booleanをまとめて扱うミニ例
最後に、数値・文字列・BooleanのState更新を1つのコンポーネントにまとめてみます。
import { useState } from "react";
function StateDemo() {
const [count, setCount] = useState(0); // 数値State
const [name, setName] = useState(""); // 文字列State
const [isOn, setIsOn] = useState(false); // Boolean State
const increment = () => {
setCount((prevCount) => prevCount + 1);
};
const toggle = () => {
setIsOn((prevIsOn) => !prevIsOn);
};
const resetName = () => {
setName("ゲスト");
};
return (
<div>
<h2>State更新デモ</h2>
<section>
<h3>数値State(count)</h3>
<p>現在のカウント:{count}</p>
<button onClick={increment}>1増やす</button>
</section>
<section>
<h3>文字列State(name)</h3>
<input
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="名前"
/>
<p>現在の名前:{name}</p>
<button onClick={resetName}>ゲストにリセット</button>
</section>
<section>
<h3>Boolean State(isOn)</h3>
<p>現在の状態:{isOn ? "ON" : "OFF"}</p>
<button onClick={toggle}>切り替え</button>
</section>
</div>
);
}
export default StateDemo;
JSXこのコンポーネントには、
- 数値Stateの更新(
setCount((prevCount) => prevCount + 1)) - 文字列Stateの更新(入力+リセット)
- Boolean Stateの更新(
setIsOn((prevIsOn) => !prevIsOn))
がすべて含まれています。
DAY 19:State更新 前半のまとめ
この前半では、
- 数値Stateでは「今の値をもとに新しい値を計算する」更新が基本であること
- 文字列Stateでは「入力値をそのままStateに反映する」パターンがよく使われること
- Boolean Stateでは「今の値を反転する」更新が典型的であること
- 「前のStateを利用する」場合には、関数型更新(
setCount((prev) => prev + 1))が安全であること - 更新関数は「新しいStateをReactに渡す窓口」であり、直接代入ではなく必ず更新関数を使うこと
をステップバイステップで確認しました。
中盤以降では、 この「安全なState更新」の考え方を、配列やオブジェクトなど、もう少し複雑なデータ構造にも広げていきます。
DAY 19:State更新 中盤 ― 「実際のUIでState更新パターンを使い分ける」
DAY 19の中盤では、前半で触れた
- 数値State
- 文字列State
- Boolean State
- 前のStateを利用する
- State更新関数
を、もう少し「実際のUI」に近い形で組み合わせていきます。 単なるサンプルではなく、ミニ機能を作りながらState更新の“クセ”を体で覚えることを目標にします。
数値State ― 「制限付きカウンター」で前のStateを意識する
上限・下限付きカウンターを作る
まず、数値Stateを使って「0〜10の範囲で動くカウンター」を作ってみます。
import { useState } from "react";
function LimitedCounter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount((prevCount) => {
if (prevCount >= 10) {
return prevCount; // これ以上増やさない
}
return prevCount + 1;
});
};
const decrement = () => {
setCount((prevCount) => {
if (prevCount <= 0) {
return prevCount; // これ以上減らさない
}
return prevCount - 1;
});
};
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={increment}>1増やす(最大10)</button>
<button onClick={decrement}>1減らす(最小0)</button>
</div>
);
}
export default LimitedCounter;
JSXここで起きていることをステップで整理すると、
countは数値Stateです。incrementでは、setCount((prevCount) => { ... })として「前のState」を受け取っています。prevCount >= 10のときは、そのままprevCountを返し、上限を超えないようにしています。decrementでも同様に、prevCount <= 0のときはそのまま返して下限を守っています。
重要ポイント:
- 「前のStateを見て条件分岐し、新しいStateを決める」場面では、関数型更新が非常に自然です。
prevCountという名前を使うことで、「これは前の値だ」と読み手にも伝わりやすくなります。
文字列State ― 「入力+リセット+追記」で更新パターンを増やす
入力値をそのままStateにする基本パターン
文字列Stateの基本は、前半で見たように「入力値をそのままStateにする」パターンです。
const [text, setText] = useState("");
<input
value={text}
onChange={(event) => setText(event.target.value)}
/>
JSXここでは、event.target.value が「新しい文字列」としてそのままStateになります。
追記・リセットを組み合わせた例
ここから一歩進めて、「追記」と「リセット」を組み合わせた例を見てみます。
import { useState } from "react";
function MessageEditor() {
const [message, setMessage] = useState("");
const appendHello = () => {
setMessage((prevMessage) => prevMessage + "こんにちは!");
};
const resetMessage = () => {
setMessage("");
};
return (
<div>
<textarea
value={message}
onChange={(event) => setMessage(event.target.value)}
placeholder="メッセージを入力してください"
/>
<p>現在のメッセージ:</p>
<pre>{message}</pre>
<button onClick={appendHello}>「こんにちは!」を追記</button>
<button onClick={resetMessage}>リセット</button>
</div>
);
}
export default MessageEditor;
JSXここで起きていることをステップで整理すると、
messageは文字列Stateです。- 入力欄の
onChangeでは、「新しい文字列」をそのままsetMessageに渡しています。 appendHelloでは、setMessage((prevMessage) => prevMessage + "こんにちは!");として「前のStateに追記」しています。resetMessageでは、setMessage("")として「新しい値を直接渡す」更新をしています。
重要ポイント:
- 文字列Stateでも、「前のStateをもとに新しい文字列を作る」関数型更新が使えます。
- 「追記」「削除」「置き換え」などの操作をするときは、前のStateを意識すると設計しやすくなります。
Boolean State ― 「複数の表示を切り替える」実用的なトグル
詳細表示のON/OFFを切り替える
Boolean Stateは、単純なON/OFFだけでなく、「詳細表示のON/OFF」などにもよく使われます。
import { useState } from "react";
function DetailToggle() {
const [showDetail, setShowDetail] = useState(false);
const toggleDetail = () => {
setShowDetail((prevShowDetail) => !prevShowDetail);
};
return (
<div>
<p>React入門 60日コース</p>
<button onClick={toggleDetail}>
{showDetail ? "詳細を隠す" : "詳細を表示"}
</button>
{showDetail && (
<div>
<p>DAY 1〜DAY 60まで、Reactの基礎から実践まで学びます。</p>
<p>1日1〜2時間を目安に進めていきます。</p>
</div>
)}
</div>
);
}
export default DetailToggle;
JSXここで起きていることをステップで整理すると、
showDetailはBoolean Stateです。toggleDetailでは、setShowDetail((prevShowDetail) => !prevShowDetail);として「前の値を反転」しています。- ボタンのラベルは、
showDetailに応じて「詳細を隠す」「詳細を表示」を切り替えています。 - 詳細部分の表示は、
{showDetail && (...)}で条件付きレンダリングをしています。
重要ポイント:
- Boolean Stateは、「表示するかしないか」「開くか閉じるか」を切り替えるのに最適です。
setShowDetail((prev) => !prev)のように、前のStateを反転する関数型更新は非常によく使われるパターンです。
前のStateを利用する ― 「連続更新」や「条件付き更新」で必須になる
「連続で増やす」ボタンを例にする
前のStateを利用する重要性がよく分かる例として、「一度のクリックで3回増やす」ボタンを考えてみます。
import { useState } from "react";
function MultiIncrementCounter() {
const [count, setCount] = useState(0);
const incrementThreeTimes = () => {
setCount((prevCount) => prevCount + 1);
setCount((prevCount) => prevCount + 1);
setCount((prevCount) => prevCount + 1);
};
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={incrementThreeTimes}>
3回増やす
</button>
</div>
);
}
export default MultiIncrementCounter;
JSXここで起きていることをステップで整理すると、
incrementThreeTimesの中で、setCountを3回呼んでいます。- それぞれの
setCountは、「前のState」をprevCountとして受け取ります。 - 1回目:
prevCountは現在のcount(たとえば0) →1に更新 - 2回目:
prevCountは「1回目の更新後の値」(1) →2に更新 - 3回目:
prevCountは「2回目の更新後の値」(2) →3に更新
結果として、1回のクリックで count が3増えます。
重要ポイント:
- 同じStateを連続で更新する場合、関数型更新を使うことで「前の更新結果」を正しく受け取れます。
setCount(count + 1);を3回書くのではなく、setCount((prev) => prev + 1);を3回書くのが安全です。
State更新関数 ― 「直接値を渡す」と「前のStateから計算する」の使い分け
2つのパターンを意識して選ぶ
State更新関数には、次の2つの使い方があります。
1. 新しい値を直接渡す
setCount(10);
setName("ゲスト");
setIsOn(true);
JSX- 「前のStateは関係なく、これにしたい」というときに使います。
- リセットや固定値への変更に向いています。
2. 前のStateをもとに新しい値を計算する(関数型更新)
setCount((prevCount) => prevCount + 1);
setName((prevName) => prevName + "さん");
setIsOn((prevIsOn) => !prevIsOn);
JSX- 「前のStateを見てから新しい値を決めたい」というときに使います。
- 連続更新・条件付き更新・追記などに向いています。
重要ポイント:
- 「前のStateを使うかどうか」で、どちらのパターンを使うかを決めます。
- 迷ったら、「前の値を見たいか?」と自分に問いかけてみると判断しやすいです。
数値・文字列・Booleanを組み合わせたミニUI
最後に、数値・文字列・BooleanのState更新を1つのミニUIにまとめてみます。
import { useState } from "react";
function MiniDashboard() {
const [count, setCount] = useState(0); // 数値State
const [name, setName] = useState("ゲスト"); // 文字列State
const [isAdmin, setIsAdmin] = useState(false); // Boolean State
const increment = () => {
setCount((prevCount) => prevCount + 1);
};
const changeName = () => {
setName((prevName) => prevName + "さん");
};
const toggleAdmin = () => {
setIsAdmin((prevIsAdmin) => !prevIsAdmin);
};
return (
<div>
<h2>ミニダッシュボード</h2>
<section>
<h3>カウント</h3>
<p>現在のカウント:{count}</p>
<button onClick={increment}>1増やす</button>
</section>
<section>
<h3>ユーザー名</h3>
<p>現在の名前:{name}</p>
<button onClick={changeName}>「さん」を付ける</button>
</section>
<section>
<h3>権限</h3>
<p>権限:{isAdmin ? "管理者" : "一般ユーザー"}</p>
<button onClick={toggleAdmin}>
権限を切り替え
</button>
</section>
</div>
);
}
export default MiniDashboard;
JSXこのコンポーネントには、
- 数値Stateの関数型更新(
prevCount + 1) - 文字列Stateの関数型更新(
prevName + "さん") - Boolean Stateの関数型更新(
!prevIsAdmin)
がすべて含まれており、 「前のStateを利用する更新」と「State更新関数の役割」をまとめて体感できる構成になっています。
DAY 19:State更新 中盤のまとめ
この中盤では、
- 数値Stateで「上限・下限付きカウンター」を作り、前のStateを見て条件付き更新するパターンを確認したこと
- 文字列Stateで「入力+追記+リセット」を組み合わせ、前のStateを使った文字列操作に慣れたこと
- Boolean Stateで「詳細表示のON/OFF」を切り替え、表示制御にStateを使う感覚をつかんだこと
- 「連続更新」や「条件付き更新」の場面で、関数型更新(
setX((prev) => ...))が必須になる理由を理解したこと - State更新関数には「新しい値を直接渡す」と「前のStateから計算する」の2パターンがあり、用途によって使い分けることが大事だと分かったこと
- 数値・文字列・BooleanをまとめたミニUIを通して、State更新パターンを実際の画面構成に当てはめて考えられるようになったこと
が大きなポイントになります。
後半では、 この「前のStateを利用する」考え方を、配列やオブジェクトなど、より複雑なデータ構造に広げていき、 Reactで実務レベルのState管理に近づいていきます。
DAY 19:State更新 後半 ― 「安全で読みやすいState更新」を習慣にする
DAY 19の後半では、これまで扱ってきた
- 数値State
- 文字列State
- Boolean State
- 前のStateを利用する
- State更新関数
をまとめて振り返りつつ、「実務でも通用する書き方」を意識して整理していきます。 ここで身につけるべきなのは、「State更新は常に“前のStateを意識して書く”」という習慣です。
数値State ― 「計算ロジックは更新関数の中に閉じ込める」
計算をコンポーネントの外に逃がさない
数値Stateを更新するとき、次のような書き方は一見シンプルですが、ロジックが散らばりやすくなります。
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
const next = count + 1;
setCount(next);
};
// ...
}
JSXこれでも動きますが、より読みやすく安全にするなら、「前のStateを受け取って、その中で計算する」形にまとめるとよいです。
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount((prevCount) => prevCount + 1);
};
const decrement = () => {
setCount((prevCount) => prevCount - 1);
};
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={increment}>1増やす</button>
<button onClick={decrement}>1減らす</button>
</div>
);
}
JSXこのように書くことで、
- 「前のStateを使って新しいStateを計算している」ことが明確になる
- 連続更新や非同期的な更新でも安全に動作する
というメリットがあります。
文字列State ― 「入力・追記・リセットをパターンとして整理する」
入力は「新しい値をそのまま渡す」パターン
文字列Stateの更新は、大きく3つのパターンに整理できます。
- 入力値をそのまま反映するjsx
const [text, setText] = useState(""); const handleChange = (event) => { setText(event.target.value); };これは「前のStateは関係なく、新しい値をそのまま使う」パターンです。 - 前のStateに追記するjsx
const appendExclamation = () => { setText((prevText) => prevText + "!"); }; - 固定値にリセットするjsx
const resetText = () => { setText(""); };
これらを1つのコンポーネントにまとめると、更新パターンが整理されて見えてきます。
function TextPatterns() {
const [text, setText] = useState("");
const handleChange = (event) => {
setText(event.target.value); // 新しい値をそのまま
};
const appendExclamation = () => {
setText((prevText) => prevText + "!");
};
const resetText = () => {
setText("");
};
return (
<div>
<textarea
value={text}
onChange={handleChange}
placeholder="入力してください"
/>
<p>現在のテキスト:</p>
<pre>{text}</pre>
<button onClick={appendExclamation}>「!」を追記</button>
<button onClick={resetText}>リセット</button>
</div>
);
}
JSX重要なのは、「前のStateを使うかどうか」で更新パターンを分けて考えることです。
Boolean State ― 「ON/OFFの意味を名前で表現する」
名前で「何がON/OFFなのか」を伝える
Boolean Stateは、名前の付け方がとても重要です。
const [isOpen, setIsOpen] = useState(false);
const [isAdmin, setIsAdmin] = useState(false);
const [showDetail, setShowDetail] = useState(false);
JSXこのように、
isOpenisAdminshowDetail
といった名前にすることで、「何がON/OFFなのか」が一目で分かります。
更新関数も、前のStateを使って反転する形が基本です。
const toggleOpen = () => {
setIsOpen((prevIsOpen) => !prevIsOpen);
};
const toggleAdmin = () => {
setIsAdmin((prevIsAdmin) => !prevIsAdmin);
};
JSXBoolean Stateは、
- 表示するかしないか
- 権限があるかないか
- モーダルが開いているか閉じているか
など、「二択の状態」を表すのに向いています。 その意味を名前で表現し、更新は「前のStateを反転する」形に統一すると、コードが非常に読みやすくなります。
前のStateを利用する ― 「ロジックをState更新関数の中に閉じ込める」
条件付き更新をすべて「prev」を起点に書く
前のStateを利用する場面では、「ロジックを更新関数の中に閉じ込める」意識が大切です。
たとえば、「0〜10の範囲でしか増減しないカウンター」は、次のように書けます。
const increment = () => {
setCount((prevCount) => {
if (prevCount >= 10) {
return prevCount;
}
return prevCount + 1;
});
};
const decrement = () => {
setCount((prevCount) => {
if (prevCount <= 0) {
return prevCount;
}
return prevCount - 1;
});
};
JSXここで、
- 「前のStateを見て条件分岐する」
- 「新しいStateを返す」
というロジックが、更新関数の中にきれいに閉じ込められています。
この書き方を習慣にすると、
- どこでStateが変わるのか
- どういう条件で変わるのか
が一目で分かるようになり、バグが減ります。
State更新関数 ― 「直接値を渡す」と「関数型更新」の使い分けを定着させる
2パターンを明確に意識する
State更新関数には、次の2つの使い方があります。
1. 新しい値を直接渡す
setCount(0); // リセット
setName("ゲスト"); // 固定値に変更
setIsAdmin(true); // 強制的に管理者にする
JSXこれは、
「前のStateは関係なく、この値にしたい」
というときに使います。
2. 前のStateをもとに新しい値を計算する(関数型更新)
setCount((prevCount) => prevCount + 1);
setName((prevName) => prevName + "さん");
setIsAdmin((prevIsAdmin) => !prevIsAdmin);
JSXこれは、
「前のStateを見てから、新しい値を決めたい」
というときに使います。
この2つを意識して使い分けることが、ReactのState更新を“安全で読みやすく”する鍵です。
まとめ用ミニテンプレート ― 「State更新の基本形」を手元に置いておく
最後に、数値・文字列・BooleanのState更新をまとめた「基本テンプレート」を示します。 これを自分のプロジェクトの最初のコンポーネントとして書いてみると、State更新の感覚が定着しやすくなります。
import { useState } from "react";
function StatePatterns() {
// 数値State
const [count, setCount] = useState(0);
const increment = () => {
setCount((prevCount) => prevCount + 1);
};
const resetCount = () => {
setCount(0);
};
// 文字列State
const [name, setName] = useState("ゲスト");
const changeName = (event) => {
setName(event.target.value);
};
const appendSan = () => {
setName((prevName) => prevName + "さん");
};
// Boolean State
const [isAdmin, setIsAdmin] = useState(false);
const toggleAdmin = () => {
setIsAdmin((prevIsAdmin) => !prevIsAdmin);
};
return (
<div>
<h2>State更新パターンまとめ</h2>
<section>
<h3>数値State</h3>
<p>count:{count}</p>
<button onClick={increment}>1増やす</button>
<button onClick={resetCount}>0にリセット</button>
</section>
<section>
<h3>文字列State</h3>
<input
value={name}
onChange={changeName}
placeholder="名前を入力"
/>
<p>name:{name}</p>
<button onClick={appendSan}>「さん」を付ける</button>
</section>
<section>
<h3>Boolean State</h3>
<p>権限:{isAdmin ? "管理者" : "一般ユーザー"}</p>
<button onClick={toggleAdmin}>権限を切り替え</button>
</section>
</div>
);
}
export default StatePatterns;
JSXDAY 19:State更新 後半のまとめ
DAY 19の後半では、
- 数値Stateの更新ロジックを「前のStateを受け取る関数の中に閉じ込める」ことで、安全性と読みやすさを高めること
- 文字列Stateの更新を「入力」「追記」「リセット」の3パターンに整理し、前のStateを使う場面と使わない場面を区別すること
- Boolean Stateの名前付けと反転更新(
prev => !prev)を通して、「何がON/OFFなのか」をコードから伝えられるようにすること - 「前のStateを利用する」更新では、関数型更新を使うことで、連続更新や条件付き更新を安全に書けること
- State更新関数には「直接値を渡す」と「前のStateから計算する」の2パターンがあり、用途に応じて使い分けること
- 数値・文字列・Booleanをまとめたテンプレートを通して、State更新の基本形を自分の手で書けるようになること
を確認しました。
ここまで来ると、ReactのState更新は「怖いもの」ではなく、「パターンとして整理できるもの」になっているはずです。 次のステップでは、この考え方を配列やオブジェクトのStateに広げていき、より実務に近いデータ構造を扱えるようになっていきます。
DAY 19:State更新 制作編 ― カウンターアプリを完成させる
DAY 19の制作では、これまで学んできたState更新の考え方を使って、カウンターアプリを実際に作っていきます。 機能はシンプルですが、ReactのStateの基本がすべて詰まっています。
+1ボタン-1ボタン- リセットボタン
を持つカウンターアプリを題材にして、
- 数値State
- 文字列State
- Boolean State
- 前のStateを利用する
- State更新関数
をステップバイステップで確認していきます。
カウンターアプリのゴールイメージを決める
まず、どんなカウンターアプリを作るかをイメージします。
- 画面中央に「現在のカウント」を表示する
+1ボタンで1増える-1ボタンで1減る- 「リセット」ボタンで0に戻る
- 状態に応じてメッセージを変える(例:0のときは「まだ何もカウントされていません」など)
この中に、数値State・文字列State・Boolean State・前のStateを利用する更新が自然に含まれるように設計していきます。
数値State ― カウンターの「現在の値」を持つ
countとsetCountを定義する
カウンターの中心となるのは、数値Stateです。 まずは、count と setCount を定義します。
import { useState } from "react";
function CounterApp() {
const [count, setCount] = useState(0);
return (
<div>
<p>現在のカウント:{count}</p>
</div>
);
}
export default CounterApp;
JSXここで起きていることを整理すると、
count→ 現在のカウントの値(数値State)setCount→countを更新するための関数useState(0)→ 初期値は0(最初は0からスタート)
重要ポイント:
- カウンターアプリでは、
countが「アプリの中心となるState」です。 - 「今いくつか」を表す値は、必ずStateとして持つようにします。
State更新関数 ― +1 / -1 / リセットの動きを定義する
+1ボタンの動き:前のStateを利用して1増やす
次に、+1 ボタンの動きを定義します。 ここでは、前のStateを利用する関数型更新を使います。
function CounterApp() {
const [count, setCount] = useState(0);
const handleIncrement = () => {
setCount((prevCount) => prevCount + 1);
};
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={handleIncrement}>+1</button>
</div>
);
}
JSXここで起きていることをステップで整理すると、
handleIncrementが呼ばれると、setCount((prevCount) => prevCount + 1);が実行されます。prevCountには「前のcountの値」が入ります。prevCount + 1を新しいStateとしてReactに渡します。- Reactが再レンダリングし、「新しい
count」に基づいて画面を更新します。
重要ポイント:
setCount((prevCount) => prevCount + 1)は、数値State更新の基本形です。- 「前のStateをもとに新しい値を計算する」場面では、関数型更新を使うのが安全です。
-1ボタンの動き:前のStateを利用して1減らす
次に、-1 ボタンの動きを定義します。
function CounterApp() {
const [count, setCount] = useState(0);
const handleIncrement = () => {
setCount((prevCount) => prevCount + 1);
};
const handleDecrement = () => {
setCount((prevCount) => prevCount - 1);
};
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={handleIncrement}>+1</button>
<button onClick={handleDecrement}>-1</button>
</div>
);
}
JSXここでも、
prevCount - 1を新しいStateとして渡しています。- 「前の値を見てから1減らす」というロジックが、更新関数の中に閉じ込められています。
リセットボタンの動き:直接値を渡して0に戻す
最後に、「リセット」ボタンを追加します。 ここでは、前のStateは関係なく、固定値に戻すので、直接値を渡す更新を使います。
function CounterApp() {
const [count, setCount] = useState(0);
const handleIncrement = () => {
setCount((prevCount) => prevCount + 1);
};
const handleDecrement = () => {
setCount((prevCount) => prevCount - 1);
};
const handleReset = () => {
setCount(0);
};
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={handleIncrement}>+1</button>
<button onClick={handleDecrement}>-1</button>
<button onClick={handleReset}>リセット</button>
</div>
);
}
JSX重要ポイント:
- 「前のStateは関係なく、特定の値にしたい」場合は、
setCount(0)のように直接値を渡します。 - 「前のStateをもとに計算したい」場合は、
setCount((prev) => ...)の関数型更新を使います。 - この使い分けが、ReactのState更新を理解するうえで非常に重要です。
文字列State ― カウンターにメッセージを添える
状態に応じてメッセージを変える
次に、文字列Stateを使って、カウンターにメッセージを添えてみます。 たとえば、
count === 0のとき → 「まだ何もカウントされていません」count > 0のとき → 「カウントが進んでいます!」count < 0のとき → 「マイナス方向にカウントしています」
というメッセージを表示することを考えます。
ここでは、文字列Stateを持つ方法と、「計算結果として文字列を表示する方法」の2つがありますが、 まずは文字列Stateとして持つパターンを見てみます。
function CounterApp() {
const [count, setCount] = useState(0);
const [message, setMessage] = useState("まだ何もカウントされていません");
const updateMessage = (nextCount) => {
if (nextCount === 0) {
setMessage("まだ何もカウントされていません");
} else if (nextCount > 0) {
setMessage("カウントが進んでいます!");
} else {
setMessage("マイナス方向にカウントしています");
}
};
const handleIncrement = () => {
setCount((prevCount) => {
const nextCount = prevCount + 1;
updateMessage(nextCount);
return nextCount;
});
};
const handleDecrement = () => {
setCount((prevCount) => {
const nextCount = prevCount - 1;
updateMessage(nextCount);
return nextCount;
});
};
const handleReset = () => {
setCount(0);
updateMessage(0);
};
return (
<div>
<p>現在のカウント:{count}</p>
<p>メッセージ:{message}</p>
<button onClick={handleIncrement}>+1</button>
<button onClick={handleDecrement}>-1</button>
<button onClick={handleReset}>リセット</button>
</div>
);
}
JSXここで起きていることをステップで整理すると、
messageは文字列Stateで、「現在の状態に応じたメッセージ」を持っています。updateMessage(nextCount)は、「次のカウント値」に応じてメッセージを更新する関数です。handleIncrementとhandleDecrementでは、prevCountからnextCountを計算しupdateMessage(nextCount)で文字列Stateを更新しnextCountを数値Stateとして返しています。
handleResetでは、数値Stateと文字列Stateを両方リセットしています。
重要ポイント:
- 数値Stateの更新に合わせて、文字列Stateも更新することで、「状態に応じたメッセージ」を表示できます。
- 「次の値」を変数にしてから、数値Stateと文字列Stateの両方に反映する書き方は、実務でもよく使われるパターンです。
Boolean State ― カウンターの「拡張機能」をON/OFFする
例えば「詳細表示ON/OFF」を追加する
Boolean Stateを使って、カウンターの拡張機能をON/OFFすることもできます。 ここでは、「詳細表示」をON/OFFする例を見てみます。
function CounterApp() {
const [count, setCount] = useState(0);
const [showDetail, setShowDetail] = useState(false);
const handleIncrement = () => {
setCount((prevCount) => prevCount + 1);
};
const handleDecrement = () => {
setCount((prevCount) => prevCount - 1);
};
const handleReset = () => {
setCount(0);
};
const toggleDetail = () => {
setShowDetail((prevShowDetail) => !prevShowDetail);
};
return (
<div>
<p>現在のカウント:{count}</p>
<button onClick={handleIncrement}>+1</button>
<button onClick={handleDecrement}>-1</button>
<button onClick={handleReset}>リセット</button>
<hr />
<button onClick={toggleDetail}>
{showDetail ? "詳細を隠す" : "詳細を表示"}
</button>
{showDetail && (
<div>
<p>このカウンターは、+1 / -1 / リセットの3つの操作ができます。</p>
<p>State更新の練習用に最適なミニアプリです。</p>
</div>
)}
</div>
);
}
JSXここで起きていることをステップで整理すると、
showDetailはBoolean Stateで、「詳細表示がONかOFFか」を表しています。toggleDetailでは、setShowDetail((prevShowDetail) => !prevShowDetail);として前のStateを反転しています。- ボタンのラベルは、
showDetailに応じて「詳細を隠す」「詳細を表示」を切り替えています。 - 詳細部分の表示は、
{showDetail && (...)}で条件付きレンダリングをしています。
重要ポイント:
- Boolean Stateは、「機能のON/OFF」「表示のON/OFF」を制御するのに非常に向いています。
setShowDetail((prev) => !prev)のような反転更新は、Reactで頻出するパターンです。
カウンターアプリ完成版テンプレート
最後に、数値State・文字列State・Boolean State・前のStateを利用する更新・State更新関数をすべて組み込んだ、カウンターアプリ完成版のテンプレートを示します。
import { useState } from "react";
function CounterApp() {
// 数値State:カウント
const [count, setCount] = useState(0);
// 文字列State:メッセージ
const [message, setMessage] = useState("まだ何もカウントされていません");
// Boolean State:詳細表示ON/OFF
const [showDetail, setShowDetail] = useState(false);
const updateMessage = (nextCount) => {
if (nextCount === 0) {
setMessage("まだ何もカウントされていません");
} else if (nextCount > 0) {
setMessage("カウントが進んでいます!");
} else {
setMessage("マイナス方向にカウントしています");
}
};
const handleIncrement = () => {
setCount((prevCount) => {
const nextCount = prevCount + 1;
updateMessage(nextCount);
return nextCount;
});
};
const handleDecrement = () => {
setCount((prevCount) => {
const nextCount = prevCount - 1;
updateMessage(nextCount);
return nextCount;
});
};
const handleReset = () => {
const nextCount = 0;
setCount(nextCount);
updateMessage(nextCount);
};
const toggleDetail = () => {
setShowDetail((prevShowDetail) => !prevShowDetail);
};
return (
<div>
<h2>カウンターアプリ</h2>
<p>現在のカウント:{count}</p>
<p>メッセージ:{message}</p>
<button onClick={handleIncrement}>+1</button>
<button onClick={handleDecrement}>-1</button>
<button onClick={handleReset}>リセット</button>
<hr />
<button onClick={toggleDetail}>
{showDetail ? "詳細を隠す" : "詳細を表示"}
</button>
{showDetail && (
<div>
<p>このアプリは、ReactのState更新の基本を練習するためのミニ教材です。</p>
<p>数値State・文字列State・Boolean Stateを組み合わせて構成されています。</p>
</div>
)}
</div>
);
}
export default CounterApp;
JSXDAY 19:カウンターアプリ制作のまとめ
この制作編では、
- 数値Stateとして
countを持ち、+1/-1/ リセットの動きをState更新関数で定義したこと - 「前のStateを利用する」関数型更新(
setCount((prev) => prev + 1))を使って、安全に数値を増減させたこと - 文字列Stateとして
messageを持ち、countに応じてメッセージを更新することで、状態に意味を持たせたこと - Boolean Stateとして
showDetailを持ち、詳細表示のON/OFFを切り替えることで、機能の拡張を表現したこと - 数値・文字列・BooleanのStateを1つのアプリの中で組み合わせ、ReactのState更新の基本パターンを実際のUIに落とし込んだこと
をステップバイステップで確認しました。
読者のみなさんが、このカウンターアプリを自分なりに改造してみることで、 State更新の感覚がさらに深く定着していきます。 例えば、「上限・下限をつける」「履歴を表示する」「ボタンを無効化する」など、 少しずつ機能を足していくと、ReactのState設計力が自然と鍛えられていきます。
