つくる - ダークモード切替

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) と書くと、同じ値を渡すことになるので何も起きません。前のレッスンで見たとおりです。

演習

プロフィールサイトにダークモード切りかえを付けます。

ヒント

App.jsx
styles.css
App.jsx
styles.css
プレビュー

できているか

  • はじめはルートの div に dark クラスが付いていない
  • ボタンを押すとダークモードになる
  • 続けてもう 1 回押すとライトモードに戻る