Last active
July 14, 2022 08:56
-
-
Save nanxiaobei/383f0657e639fb4246332ff8b977b858 to your computer and use it in GitHub Desktop.
returns isDark state, and a switch function for dark mode button
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const useDarkMode = (): [boolean, () => void] => { | |
const [isDark, setIsDark] = useState(false); | |
const setDark = (newDark: boolean) => { | |
document.documentElement.classList[newDark ? 'add' : 'remove']('dark'); | |
localStorage.setItem('dark', `${newDark}`); | |
setIsDark(newDark); | |
}; | |
useEffect(() => { | |
const darkScheme = window.matchMedia('(prefers-color-scheme: dark)'); | |
// init | |
setDark(localStorage.getItem('dark') === 'true' || darkScheme.matches); | |
// listen system | |
const onChange = (event: MediaQueryListEvent) => { | |
setDark(event.matches); | |
}; | |
darkScheme.addEventListener('change', onChange); | |
return () => { | |
darkScheme.removeEventListener('change', onChange); | |
}; | |
}, []); | |
// manual switch | |
return [ | |
isDark, | |
useCallback(() => { | |
setDark(localStorage.getItem('dark') !== 'true'); | |
}, []), | |
]; | |
}; | |
export default useDarkMode; |
两次指的是有两个组件分别调用了 useDarkMode
,这样 media query 的 listener 就被注册了两次,因而产生一些意料之外的效果。这么想的原因是我感觉这个 hook 应该是可以被多次调用的,一个 app 中有多个地方需要判断和设置 dark mode 也比较常见。
嗯有道理,如果两个组件使用,会被注册两次,不过行为应该是一致的,因为系统的 Dark Mode 情况是唯一的。
担心错乱可以设置全局标记,在注册前判断是否已注册。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
嗯嗯可以兼容一下
const darkScheme = window?.matchMedia('(prefers-color-scheme: dark)')