つくる - ダークモード切替
JavaScript 版を思い出す
JavaScript 入門でダークモードを作ったときは、こんなコードでした。
const button = document.querySelector("#toggle");
const page = document.querySelector("#page");
button.addEventListener("click", () => {
page.classList.toggle("dark");
button.textContent = page.classList.contains("dark")
? "ライトモードにする"
: "ダークモードにする";
});要素を探して、クラスを足したり外したり、ボタンの文字も自分で書きかえていました。「今どちらのモードなのか」は DOM のクラスを調べないと分かりません。つまり 画面が状態を持っている 状態です。
React 版の考え方
React では逆にします。真実は state のほうに置き、画面は state から作ります。
const [isDark, setIsDark] = useState(false);isDark が true か false か、それだけが「今のモード」です。あとは表示をそこから組み立てます。
<div className={isDark ? "page dark" : "page light"}>クラス名も文字列なので、三項演算子でどちらを使うか選べます。classList.toggle は使いません。ボタンの文字も同じやり方です。
<button onClick={() => setIsDark(!isDark)}>
{isDark ? "ライトモードにする" : "ダークモードにする"}
</button>!isDark で真偽値をひっくり返しています。切りかえたい状態が 2 つしかないときの定番です。
変えるところは 1 か所だけ
JavaScript 版では「クラスを変える処理」と「ボタンの文字を変える処理」が別々にあり、片方だけ直し忘れると表示がちぐはぐになりました。React 版で書きかえるのは isDark だけです。クラスもボタンの文字も、そこから毎回作り直されるので、ずれようがありません。
これが第 1 章で出てきた宣言的 UI の実感できる形です。手順を書くのではなく、状態と見た目の対応を書いています。
CSS の当て方
スタイルはこれまでどおり CSS ファイルに書きます。ルートの div に付くクラスが変わるので、その下の要素の色もまとめて変えられます。
.page {
padding: 24px;
}
.page.light {
background: #ffffff;
color: #252525;
}
.page.dark {
background: #252525;
color: #f5f5f5;
}つまずきどころ
className を波かっこにするのを忘れて className="isDark ? ..." と書くと、そのままの文字列がクラス名になります。式を使うときは必ず波かっこです。
もう 1 つ、setIsDark(!isDark) の ! を忘れて setIsDark(isDark) と書くと、同じ値を渡すことになるので何も起きません。前のレッスンで見たとおりです。
演習
プロフィールサイトにダークモード切りかえを付けます。