複数のstate
state はいくつでも作れる
画面が持つ状態は 1 つとはかぎりません。プロフィールサイトなら、いいね数のほかに「今どのタブを開いているか」「表示名は本名かローマ字か」なども状態です。
useState は必要なだけ並べて書けます。
import { useState } from "react";
export default function App() {
const [likes, setLikes] = useState(0);
const [activeTab, setActiveTab] = useState("プロフィール");
const [displayName, setDisplayName] = useState("あおい");
...
}それぞれ独立していて、片方を更新してももう片方は影響を受けません。タブを切りかえてもいいね数は 0 に戻りませんし、表示名を変えてもタブは開いたままです。
1 つにまとめないほうがよい理由
「まとめて 1 つのオブジェクトにすればいいのでは」と思うかもしれません。
const [ui, setUi] = useState({ activeTab: "プロフィール", displayName: "あおい" });こう書くと、タブだけ変えたいときも setUi({ ...ui, activeTab: "作品" }) のように毎回オブジェクトを作り直すことになります。書き忘れると消えたほうのキーが undefined になります。関係のない値どうしは別の state に分けるほうが、書くのも読むのも簡単です。
まとめるのは「必ず一緒に変わる値」のときだけです。プロフィールの名前と肩書きと自己紹介のように、1 つのフォームでまとめて編集するものは 1 つのオブジェクトにする価値があります。これは次のレッスンで扱います。
タブを state で持つ
タブの実装は「今選ばれているタブの名前を state に入れておき、表示をそれで切りかえる」だけです。
import { useState } from "react";
export default function App() {
const [activeTab, setActiveTab] = useState("プロフィール");
return (
<div>
<button onClick={() => setActiveTab("プロフィール")}>プロフィール</button>
<button onClick={() => setActiveTab("作品")}>作品</button>
<p>表示中 {activeTab}</p>
</div>
);
}押されたボタンに応じて activeTab が入れかわり、<p> の中身が変わります。
切りかえる形
2 つの値を行き来させたいときは、今の値を見て反対側を渡します。
function toggleName() {
setDisplayName(displayName === "あおい" ? "aoi" : "あおい");
}三項演算子でどちらを渡すか決めています。真偽値の state なら setIsOpen(!isOpen) のように否定するだけで切りかわります。
つまずきどころ
state が増えてくると、更新関数を取りちがえて setActiveTab に名前を入れてしまうような事故が起きます。名前は必ず set + 値の名前 にそろえ、宣言は関連する順にまとめて書いておくと防げます。
演習
タブの state に加えて、表示名の state を用意し、2 つが独立して動くことを確かめます。