[英]Gatsby dark mode toggle not working on homepage in Safari
我刚刚在我的 Gatsby 网站中集成了一个明暗模式切换。 我基于Josh Comeau 的文章,它在 Chrome 中运行良好。 但是在主页上使用 Safari 时,当我单击切换按钮时,除非我调整 window 的大小,否则背景颜色不会改变。 这是我的gatsby-ssr.js
:
import React from 'react';
import { THEME_COLORS } from 'utils/theme-colors';
import { LOCAL_STORAGE_THEME_KEY } from './src/contexts/ThemeContext';
const SetTheme = () => {
let SetThemeScript = `
(function() {
function getInitialTheme() {
const persistedColorPreference = window.localStorage.getItem('${LOCAL_STORAGE_THEME_KEY}');
const hasPersistedPreference = typeof persistedColorPreference === 'string';
if (hasPersistedPreference) {
return persistedColorPreference;
}
const mql = window.matchMedia('(prefers-color-scheme: dark)');
const hasMediaQueryPreference = typeof mql.matches === 'boolean';
if (hasMediaQueryPreference) {
return mql.matches ? 'dark' : 'light';
}
return 'light';
}
const colorMode = getInitialTheme();
const root = document.documentElement;
root.style.setProperty(
'--color-primary',
colorMode === 'dark'
? '${THEME_COLORS.dark}'
: '${THEME_COLORS.light}'
);
root.style.setProperty(
'--color-secondary',
colorMode === 'dark'
? '${THEME_COLORS.light}'
: '${THEME_COLORS.dark}'
);
root.style.setProperty(
'--color-accent',
colorMode === 'dark'
? '${THEME_COLORS.accentLight}'
: '${THEME_COLORS.accentDark}'
);
root.style.setProperty('--initial-color-mode', colorMode);
})()`;
return <script id="theme-hydration" dangerouslySetInnerHTML={{ __html: SetThemeScript }} />;
};
export const onRenderBody = ({ setPreBodyComponents }) => {
setPreBodyComponents(<SetTheme />);
};
和我的ThemeToggle
组件:
import React, { useContext } from 'react';
import { ThemeContext } from 'contexts/ThemeContext';
import { DarkModeSwitch } from 'react-toggle-dark-mode';
import { THEME_COLORS } from 'utils/theme-colors';
import s from './ThemeToggle.scss';
export const ThemeToggle = () => {
const { theme, toggleTheme } = useContext(ThemeContext);
const toggleDarkMode = (checked: boolean) => {
toggleTheme(checked ? 'dark' : 'light');
};
return (
<div className={s.toggler}>
<DarkModeSwitch
checked={theme === 'dark'}
onChange={toggleDarkMode}
size={20}
sunColor={THEME_COLORS.dark}
moonColor={THEME_COLORS.light}
/>
</div>
);
};
有想法该怎么解决这个吗?
从ThemeContext
值解构的toggleTheme
属性似乎不会触发重新渲染,但调整浏览器 window 的大小会触发。 Josh 通过提供一个带有副作用的设置器 function 来处理这个问题(它直接操作根 styles):
const contextValue = React.useMemo(() => {
function setColorMode(newValue) {
const root = window.document.documentElement;
localStorage.setItem(COLOR_MODE_KEY, newValue);
Object.entries(COLORS).forEach(([name, colorByTheme]) => {
const cssVarName = `--color-${name}`;
root.style.setProperty(cssVarName, colorByTheme[newValue]);
});
rawSetColorMode(newValue);
}
return {
colorMode,
setColorMode,
};
}, [colorMode, rawSetColorMode]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.