複数の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 つが独立して動くことを確かめます。

ヒント

App.jsx
App.jsx
プレビュー

できているか

  • はじめは「あおいのプロフィール」と表示されている
  • 切りかえボタンを押すと表示名が aoi になる
  • 続けてタブを 作品 に切りかえても、表示名は aoi のまま残る