Reactのカスタムフックでダークモード切り替えを実装する方法
生徒
「Reactでダークモードを切り替える機能を作りたいんですが、どうすればいいですか?」
先生
「ダークモードの切り替えには、状態を管理してスタイルを変える方法がありますよ。」
生徒
「なるほど!でも、毎回同じコードを書くのは面倒ですね……」
先生
「そんなときは、カスタムフックを使うと便利です。共通の処理をひとつの関数にまとめられます。」
生徒
「カスタムフックって何ですか?」
先生
「では、Reactのカスタムフックを使ってダークモードを実装する方法を一緒に見ていきましょう!」
1. カスタムフックとは?
まず、「カスタムフック」という言葉を聞いたことがない人のために説明しましょう。カスタムフックとは、Reactで用意されているフック(たとえば useState や useEffect)を組み合わせて、自分専用の便利な機能を作る仕組みのことです。
名前のルールとしては、必ず「use」から始めます。たとえば今回の例では、useDarkModeという関数名にします。
これを使うと、複数のコンポーネントで同じロジックを簡単に使い回せるようになります。
2. ダークモード切り替えの仕組みを考えよう
ダークモードとは、背景を暗くして目に優しい表示に切り替えるデザインのことです。スマートフォンやWebサイトでもよく見かけますね。
Reactでダークモードを実装するには、次のような流れになります。
- 状態(オン/オフ)を管理する
- ボタンで状態を切り替える
- 状態に応じてクラス名やスタイルを変更する
これをそのままコンポーネントに書くと長くなってしまうので、カスタムフックにまとめるのが便利です。
3. カスタムフックを作成しよう
では実際に、カスタムフックuseDarkModeを作ってみましょう。このフックは、現在のモード(ライトまたはダーク)と、モードを切り替える関数を返すようにします。
import { useState, useEffect } from "react";
function useDarkMode() {
const [isDarkMode, setIsDarkMode] = useState(false);
// ページのテーマを切り替える関数
const toggleDarkMode = () => {
setIsDarkMode((prev) => !prev);
};
// モードが変わるたびにHTML全体のクラスを変更
useEffect(() => {
if (isDarkMode) {
document.body.classList.add("dark");
} else {
document.body.classList.remove("dark");
}
}, [isDarkMode]);
return [isDarkMode, toggleDarkMode];
}
export default useDarkMode;
このフックでは、状態管理のuseStateと副作用を扱うuseEffectを組み合わせています。ボタンを押すたびに状態を切り替え、その結果として背景のテーマも変更されます。
4. カスタムフックをReactコンポーネントで使う
作成したカスタムフックを、実際のコンポーネントで使ってみましょう。下記のコードでは、ボタンを押すとライトモードとダークモードが切り替わります。
import React from "react";
import useDarkMode from "./useDarkMode";
function App() {
const [isDarkMode, toggleDarkMode] = useDarkMode();
return (
<div className={isDarkMode ? "dark-mode" : "light-mode"}>
<h1>{isDarkMode ? "ダークモード" : "ライトモード"}</h1>
<button onClick={toggleDarkMode}>
モードを切り替える
</button>
</div>
);
}
export default App;
5. スタイルを設定して見た目を変える
次に、ライトモードとダークモードで色を変えるためのCSSを追加します。
body.light-mode {
background-color: white;
color: black;
}
body.dark-mode {
background-color: #121212;
color: white;
}
これで、Reactアプリ全体の背景色や文字色がモードに応じて切り替わるようになります。
6. localStorageで状態を保存する
ダークモードの状態をブラウザを閉じても保持したい場合は、localStorageを使って保存できます。
useEffect(() => {
const savedMode = localStorage.getItem("theme");
if (savedMode === "dark") {
setIsDarkMode(true);
}
}, []);
useEffect(() => {
localStorage.setItem("theme", isDarkMode ? "dark" : "light");
}, [isDarkMode]);
これを追加することで、ユーザーが前回選択したモードが次回も維持されます。
7. ダークモード対応のポイント
実際のアプリでは、単に色を反転させるだけでなく、画像やボタンの色、アイコンのコントラストなども調整が必要になります。デザイン面でも「見やすさ」「可読性」「目の疲れにくさ」を意識しましょう。
また、OSの設定に合わせて自動でダークモードを適用することも可能です。これはwindow.matchMediaという機能を使って検出できます。
useEffect(() => {
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
if (prefersDark) setIsDarkMode(true);
}, []);
これにより、ユーザーが普段ダークテーマを使っている場合、自動的にダークモードが反映されるようになります。
8. 実践に使えるカスタムフック設計のコツ
カスタムフックを作るときは、1つの責務に絞るのがポイントです。今回の例では「テーマ切り替え」だけを担当させました。
- 状態を管理するフックは、機能ごとに分ける
- 他のコンポーネントからも再利用できるように設計する
- ファイル名は
use〇〇.jsとして管理するとわかりやすい
こうすることで、チーム開発や大規模プロジェクトでも読みやすく保守しやすいコードになります。
ダークモードの切り替え機能は、ユーザーの快適さを大きく向上させる重要な機能です。今回学んだカスタムフックを使えば、シンプルで再利用性の高い実装が可能になります。
まとめ
Reactでダークモードを切り替える仕組みを振り返ると、画面全体のテーマを自在に変更できる機能は、見やすさや使いやすさを高めるうえで非常に大切であることがわかります。特に、カスタムフックという考え方を取り入れることで、テーマ切り替えのロジックをひとつの関数にまとめ、複数のコンポーネントで共通して利用できるという利点があります。こうした工夫により、コードの重複が減り、管理しやすく読みやすい構造になります。また、ダークモードの切り替えでは、状態を管理するだけでなく、背景色や文字色の変更、利用者の環境に応じた自動判定、前回の設定を保存する機能など、アプリ全体の体験向上につながる多くのポイントが含まれています。 さらに、Reactの状態管理や副作用処理を応用することで、テーマ変更のたびに必要な処理を自然な流れで実行できるようになります。ダークモードの切り替えは単なる色の変更だけではなく、コンテンツ全体の見え方、可読性、操作性に影響する大切な機能であり、カスタムフックを使うことで柔軟で拡張しやすい実装が可能になります。特に、localStorageを使ったテーマ保存は、利用者が次回アクセスした際にも前回の設定を維持できるため、快適な閲覧体験を提供する重要な要素です。 以下は、今回学んだ内容を基にしたサンプルコードです。ダークモードの切り替え機能をより理解しやすくするために、Reactのカスタムフックを使った基本的な仕組みを示しています。
テーマ切り替えサンプルコード
import { useState, useEffect } from "react";
function useThemeToggle() {
const [isDark, setIsDark] = useState(false);
const changeTheme = () => {
setIsDark(prev => !prev);
};
useEffect(() => {
if (isDark) {
document.body.classList.add("dark-mode");
} else {
document.body.classList.remove("dark-mode");
}
}, [isDark]);
return [isDark, changeTheme];
}
export default useThemeToggle;
このサンプルでは、テーマの状態を保持し、それに応じてクラス名を動的に切り替える処理を行っています。状態が変化するたびに画面全体の雰囲気が切り替わるため、利用者はより快適にサイトを閲覧できます。また、カスタムフック化することで、他のコンポーネントからも簡単に呼び出せるようになり、開発の効率が大きく向上します。ダークモードは視認性の向上やデザインの統一にも役立ち、現代のアプリ開発で欠かせない要素のひとつと言えるでしょう。
生徒
「ダークモードの切り替えって、最初は難しそうと思っていましたが、カスタムフックでまとめられるとすごく整理されてわかりやすくなりました!」
先生
「そうだね。状態管理と副作用の流れが理解できれば、テーマ切り替えのような機能も簡単に扱えるようになるよ。」
生徒
「localStorageで保存しておくことで、次にアクセスしたときも設定が維持されるのが便利でした。こうした機能は実際のサイトでもよく使われますよね?」
先生
「その通り。利用者の快適さを考えると、テーマ保持の仕組みはとても重要なんだ。今回覚えたカスタムフックの考え方は他の場面にも応用できるから、いろいろ試してみるといいよ。」
生徒
「はい!これから他の機能でもカスタムフックを使ってみたいと思います!」