📒

OSテーマ変更を検知して状態を更新

に公開

全体コード

import { useEffect, useState } from "react"

export function useIsDarkMode() {
  const [isDarkMode, setIsDarkMode] = useState(() => {
    if (typeof window === "undefined") return false

    return window.matchMedia("(prefers-color-scheme: dark)").matches
  })

  useEffect(() => {
    const controller = new AbortController()
    window.matchMedia("(prefers-color-scheme: dark)").addEventListener(
      "change",
      e => {
        setIsDarkMode(e.matches)
      },
      { signal: controller.signal }
    )

    return () => {
      controller.abort()
    }
  }, [])

  return isDarkMode
}

状態管理

const [isDarkMode, setIsDarkMode] = useState(() => {
  if (typeof window === "undefined") return false

  return window.matchMedia("(prefers-color-scheme: dark)").matches
})
  • 初期化関数をuseStateの引数に渡し、その戻り値を初期Stateとする
  • システム設定をブラウザが検知して、CSS側で自動的に切り替えることができます。そのCSSの条件が (prefers-color-scheme: dark)

イベントリスナーとクリーンアップ

const controller = new AbortController()

window.matchMedia("(prefers-color-scheme: dark)").addEventListener(
  "change",
    e => {
      setIsDarkMode(e.matches)
    },
   { signal: controller.signal } // リスナーを管理
 )
 
return () => {
  controller.abort()  // リスナー解除
}

Discussion