我的网站有浅色和深色主题。默认主题为light
。如果用户将主题更改为dark
,则会将其保存到localStorage
。
在我的组件树的根目录下一次访问/刷新时,此代码运行:
useLayoutEffect(() => {
let storedTheme = localStorage.getItem("theme");
if (storedTheme === "light" || storedTheme === "dark") {
// Redux action. Other components subscribe to the theme.
setTheme(storedTheme);
}
}, [setTheme]);
说用户选择深色主题作为他们的偏好。工作正常。但是,第一个渲染将是灯光主题。第二个渲染将是深色主题。造访该网站时,这会引起灯光暗闪烁。
有没有办法确保我的第一个渲染具有localStorage
中的设置值?
答案 0 :(得分:0)
将主题保存到本地存储的方法如下。
const [storedTheme, setStoredTheme] = useState(JSON.parse(localStorage.getItem("theme")) || "light");
useEffect(() => {
localStorage.setItem("theme", JSON.stringify(storedTheme));
}, [storedTheme]);
然后在App UI中使用方法setStoredTheme()将主题设置为“亮”或“暗”。
答案 1 :(得分:0)
将数据保存到我的第一个渲染中的工作是初始化redux存储,如下所示:
if (typeof localStorage != "undefined") {
initialState = {
theme: localStorage.getItem("theme"),
};
} else {
initialState = {};
}
const store = createStore(reducers, initialState);
但是这使情况变得更糟,因为在第一次加载时就不再重新渲染组件,因为来自redux的theme
道具从未更改过,因为商店是使用用户首选项初始化的。所以我回到上面的原始问题中的旧方法。
之所以会发生闪烁,是因为我使用Javascript控制我的react应用程序中的主题。我还在使用Gatsby,它会生成我网站的静态版本,该网站会在我的React应用之前加载。
加载网站的过程如下:
例如具有黑暗主题首选项的用户访问。他们会看到静态内容而没有任何Javascript,而JS捆绑包则会在后台下载。
由于默认为light主题,因此网站的静态版本为light。
Javascript加载,React的第一个渲染发生,并且Redux存储被初始化。根组件从localStorage
获取主题,树以深色主题重新呈现。
由于2到3之间的事件而发生闪烁。
我无法完全解决问题。但是,通过启用Gatsby的服务人员,我设法减轻了闪烁现象,使其更加不明显。工作人员会缓存Javascript捆绑包,以便下次访问网站,而从磁盘加载Javascript意味着闪烁将持续更短的时间,因为JS捆绑包已经可以执行了。