当サイトは、アフィリエイト広告を利用しています

【React × Emotion】ThemeProviderの使い方

作成日:2022月08月19日
更新日:2024年02月12日

ReactでEmotionのThemeProviderを使って簡易darkmodeを
実装しtheme切り替えの動きを確認してみる。

ThemeProviderとは?

EmotionのThemeProviderとはThemeProviderコンポーネントにpropsでオブジェクトを渡すと
ThemeProviderコンポーネントでラップしたコンポーネント内でpropsに渡したオブジェクトを
参照することができるようになる。
※hooksのuseContextみたいなイメージ。

簡易darkmodeを実装する

ThemeProviderを使って簡易darkmodeを実装し、動きを確認する

動作確認環境

動作確認環境は下記参照

package.json
"dependencies": {
"@emotion/react": "11.8.2",
"react": "18.0.0",
"react-dom": "18.0.0",
"react-scripts": "4.0.0"
},
"devDependencies": {
"@babel/runtime": "7.13.8"
},

ThemeProvider

themeProviderを使ってComponentA,ComponentB,ComponentCの
themeを切り替える

App.jsx
/** @jsxImportSource @emotion/react */
import "./styles.css";
import ComponentA from "./componentA";
import ComponentB from "./componentB";
import ComponentC from "./componentC";
import { ThemeProvider } from "@emotion/react";
import React, { useState } from "react";
// テーマを定義する
// ライトテーマ
const lightTheme = {
mode: "light",
background: "#ffffff",
color: "#000000"
};
// ダークテーマ
const darkTheme = {
mode: "dark",
background: "#222639",
color: "#f0f5fa"
};
export default function App() {
// テーマをstateで保持
const [theme, setTheme] = useState(darkTheme);
// テーマを切り替える関数
const changeTheme = (mode) => {
if (mode === "dark") {
return lightTheme;
} else {
return darkTheme;
}
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>React + Emotion + ThemeProvider</h2>
<ThemeProvider theme={theme}>
<ComponentA />
<ComponentB />
<ComponentC />
</ThemeProvider>
<button onClick={() => setTheme(({ mode }) => changeTheme(mode))}>
Theme change
</button>
</div>
);
}
  • themeはlightモードとdarkモードを用意する
  • 適用するthemeをhooksのuseStateで保持する
  • stateに保持させているthemeをThemeProviderにpropsで渡す
  • ボタンクリックでstateのthemeを切り替える
    • stateのthemeが変わるとThemeProviderに渡しているpropsも切り替わる

ラップされているコンポーネント

ラップされているコンポーネントでThemeProviderに渡したthemeを
参照することができる。
参照する方法としては下記の2つあがる

  • propsから参照する(暗黙的にpropsにわたされる)
  • useThemeを使って参照する 

propsから参照する(暗黙的にpropsにわたされる)

ThemeProviderに渡したpropsのthemeを参照してスタリングを行うことで
propsが切り替わるとthemeが切り替わるようになる。

ComponentA
/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";
const ComponentA = () => {
return <div css={[style]}>hello ComponentA</div>;
};
export default ComponentA;
// themeProviderに渡したthemeを暗黙的にpropsから参照できる
const style = (theme) => {
return [
css`
color: ${theme.color};
background-color: ${theme.background};
`
];
};
  • ThemeProviderに渡したthemeは暗黙的に参照できる
  • componentCは一緒なので割愛

useThemeを使って参照する

EmotionのuseTheme()メソッドを使って明示的にthemeを取得することもできる。

componentB.jsx
/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";
import { useTheme } from "@emotion/react";
const ComponentB = () => {
//theme取得
const theme = useTheme();
const style = () => {
return [
css`
color: ${theme.color};
background-color: ${theme.background};
`
];
};
return <div css={[style]}>hello ComponentB</div>;
};
export default ComponentB;
  • 明示的に書いた方がわかりやすいかも

動作確認

動作を確認する

React + Emoion + ThemeProvider

まとめ

emotionを使用している場合はThemeProviderを使うと簡単にテーマを切り替えることができる
ことがわかった。
今回はThemeProviderの動きを見るため最小限の実装しかしていないため
hooksはuseStateしか使っていないが、実際ホームページ等で使用する場合は
hooksのuseContextも使う必要がある。
当ブログのdarkmodeはこの方式で実装してます。
詳しくは下記記事にまとめています。

新着記事

タグ別一覧
top