【React】React-ToastifyのカラーテーマとPCの外観モードを連動させる方法【TypeScript】

はじめに

Webアプリでユーザー情報の変更などを行った際、処理が正常に完了したことをユーザーに伝えるために、画面の端に一時的にメッセージを表示する機能のことを「トースト」といいます。

トーストとは、主にデスクトップアプリケーションの機能で、情報通知用の小さなウィンドウをディスプレイの下方から一時的にポップアップ表示することである。

トーストとは 「トースト表示, トーストポップアップ」 (Toast): - IT用語辞典バイナリ

トーストを実装するのはそれほど難しくありませんが、プラグインも豊富に提供されているのでそれらを利用すると手軽に導入することができます。今回は、トースト機能を提供するReact-Toastifyというプラグインにおいて、PCの外観モードとトーストのカラーテーマを動的に連動させる方法について説明します。

PCの外観モードとトーストのテーマを連動させる

PCの外観モード

Macの場合、アップルメニュー > システム環境設定 > 一般メニューの中で外観モードを変更することができます。

CSSのprefers-color-schemeを使うことで、Webデザインでも外観モードに合わせたカラーテーマを実装できるようになりました。最近はライトテーマ/ダークテーマ/外観モード準拠のいずれかからカラーテーマを選べるWebサイトが増えてきています。

最近人気のCSSフレームワークであるTailwind CSSでは、クラス名の先頭にdark:をつけるだけで簡単にダークテーマを実装することができます。

React-Toastifyのカラーテーマ

React-Toastifyのカラーテーマはオプションで指定することができます。以下の例では、トーストのカラーテーマとしてdarkを指定しています(6行目)。カラーテーマはlight dark coloredのいずれかを指定することができます。

import { ToastContainer, toast } from 'react-toastify'

function App(){
  const notify = () => {
    toast("Wow so easy!", {
      theme: "dark",
    })
  }

  return (
    <div>
      <button onClick={notify}>Notify!</button>
      <ToastContainer />
    </div>
  )
}

React-ToastifyのカラーテーマはPCの外観モードと連動しているわけではありません。例えば、Tailwind CSSなどを使ってWebサイト全体のカラーテーマをPCの外観モードと連動するようにしていても、React-Toastifyのトーストだけ異なるカラーテーマで表示されてしまう可能性があります。PCの外観モードをダークテーマに設定しており、Webサイトのカラーテーマも連動してダークテーマになっているのに、トーストのカラーテーマだけライトテーマになっていたりすると少し残念です。

React-Toastifyのカラーテーマを動的に設定

React-Toastifyのカラーテーマを動的に設定するには、まずJavaScriptの処理でPCの外観モードを確認します。

if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
  // PCの外観モードはダークテーマに設定されている
}

この処理を使って、React-Toastifyのカラーテーマに設定する変数を用意します。

let mode = "light"
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
  mode = "dark"
}

用意した変数を使ってReact-Toastifyのカラーテーマを設定します。

let mode = "light"
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
  mode = "dark"
}
toast("Wow so easy!", {
  theme: mode,
})

さて、JavaScriptであればこれだけで設定できたかと思います。しかし、TypeScriptだと次のような静的解析エラーが出ているはずです。

型 'string' を型 'Theme | undefined' に割り当てることはできません。ts(2322)

string型のmode変数をTheme | undefined型のthemeに設定することはできないというエラー内容です。実は、React-Toastifyのthemeオプションはstring型ではなくTheme型というReact-Toastify内部で定義された型を使用しています。そのため、lightdarkといった単なる文字列が入っているだけの変数を設定しようとすると静的解析エラーが発生するというわけです。

この静的解析エラーが出ていてもWebアプリが動かなくなるわけではありません。それどころか、React-Toastifyのトーストも表示されますし、ちゃんとPCの外観モードと連動したカラーテーマが設定されています。しかし、エラーが残っているのは気持ち悪いし、ちゃんと解決する方法があります。

React-Toastifyのカラーテーマに設定する変数の宣言時に、React-Toastifyのthemeオプションで使用するTheme型を指定します。

let mode: Theme = "light"

React-Toastifyのカラーテーマに設定する変数がTheme型として定義されたため、上記の静的解析エラーは解消されました。しかし、今度は次のような静的解析エラーが出ているかと思います。

名前 'Theme' が見つかりません。ts(2304)

Theme型はReact-Toastify内部で定義された型のため、型定義をインポートする必要があります。

import { ToastContainer, toast, Theme } from 'react-toastify'

これで静的解析エラーはすべて解消されたかと思います。動作確認し、トーストのカラーテーマがPCの外観モードと連動していることを確認してください。まとめると、以下のような実装になります。

import { ToastContainer, toast, Theme } from 'react-toastify'

function App(){
  const notify = () => {
    let mode: Theme = "light"
    if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
      mode = "dark"
    }
    toast("Wow so easy!", {
      theme: mode,
    })
  }

  return (
    <div>
      <button onClick={notify}>Notify!</button>
      <ToastContainer />
    </div>
  )
}

まとめ

トースト機能を提供するReact-Toastifyというプラグインにおいて、PCの外観モードとトーストのカラーテーマを動的に連動させる方法について説明しました。この方法について検索してみたのですが、明確に解説している情報を見つけることはできませんでした。Stack Overflowで質問している人はいましたが、回答している人はいませんでした。

トースト機能があるとUXが向上し、Webアプリの利便性が向上します。トースト機能を実装するプラグインはいろいろありますが、React-Toastifyは簡単に導入でき、デザインに優れ、カスタマイズ性も高いので非常におすすめです。

関連記事

【React】React イチから学習《発展編》
# データフェッチングとパフォーマンス最適化 ## useSWRフック: データのキャッシングと再検証の最適化 `useSWR`は、Next.jsチームが開発したデータ取得ライブラリで、キャッシュ戦略とリアルタイムデータ更新のバランスを取り [...]
2024年10月21日 17:02
【React】React イチから学習《基礎編》
# Reactの基本 ## Reactとは? Reactは、Facebookによって2013年にリリースされたフロントエンドライブラリで、主にユーザーインターフェース (UI) の構築に使われます。Reactの特徴は、「コンポーネント指向の [...]
2024年10月21日 16:43
強力なUIコンポーネントライブラリ「MUI(Material-UI)」について《トラブルシューティング編》
# よくある質問とトラブルシューティング MUI(Material-UI)を使用していると、初心者でも経験者でも共通して直面しやすいエラーや問題がいくつか存在します。この章では、よく発生するエラーとその解決方法、ドキュメントでは見つけにくい設定の [...]
2024年10月15日 13:41
強力なUIコンポーネントライブラリ「MUI(Material-UI)」について《テーマ・スタイリング編》
# MUIのテーマカスタマイズ MUI(Material-UI)はデフォルトのテーマをベースに、簡単にテーマをカスタマイズできる柔軟なシステムを提供しています。これにより、アプリケーションのデザインをブランドや要件に合わせて調整可能です。 [...]
2024年10月15日 11:56
強力なUIコンポーネントライブラリ「MUI(Material-UI)」について《コンポーネント編》
# 基本的なコンポーネントの使用方法 MUIは、豊富なUIコンポーネントを提供しており、それを使うことでReactアプリケーションの開発を迅速に進められます。 ここでは、MUIでよく使用される基本的なコンポーネントであるボタン、テキストフィ [...]
2024年10月15日 10:32
強力なUIコンポーネントライブラリ「MUI(Material-UI)」について《概要編》
# はじめに ウェブアプリケーションの開発において、デザインと使いやすさを両立することは非常に重要です。MUI(Material-UI)は、Reactと組み合わせて簡単に洗練されたユーザーインターフェースを構築できる強力なUIコンポーネントライブ [...]
2024年10月15日 10:10
RailsアプリにおけるReactの使い方や注意点など
# はじめに [こちらのページ](https://qiita.com/TsutomuNakamura/items/72d8cf9f07a5a30be048)でReactの基本について勉強しました。 Railsアプリの中でReactを利用するとい [...]
2019年12月13日 12:37
【Rails】Railsアプリにreact-railsを追加する手順
# はじめに JavaScriptフレームワークといえば長らくjQuery一強でした。しかし、ここ数年はAngularJSやReact、Vue.jsといった新しいフレームワークがどんどんと登場しています。過去5年間の検索回数の推移を見てみると、2 [...]
2019年12月11日 15:21