温馨提示:本文翻译自stackoverflow.com,查看原文请点击:javascript - How do I make sure my first render with React has a value from localStorage?
javascript reactjs frontend

javascript - 如何确保我使用React的第一个渲染具有来自localStorage的值?

发布于 2020-03-27 11:53:21

我的网站有一个明暗主题。默认主题为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

查看更多

查看更多

提问者
Osama Qarem
被浏览
18
Osama Qarem 2019-07-03 23:22

将数据保存到我的第一个渲染中的工作是初始化redux存储,如下所示:

if (typeof localStorage != "undefined") {
  initialState = {
    theme: localStorage.getItem("theme"),
  };
} else {
  initialState = {};
}

const store = createStore(reducers, initialState);

但这使情况变得更糟,因为在第一次加载时就不再重新渲染组件,因为theme来自redux prop从未更改过,因为商店是使用用户首选项初始化的。所以我回到上面的原始问题中的旧方法。

之所以会发生闪烁,是因为我使用Javascript控制我的react应用程序中的主题。我还使用Gatsby,它会生成我网站的静态版本,该网站会在我的react应用之前加载。

加载网站是这样的:

  1. 例如,具有深色主题首选项的用户访问。他们看到静态内容而没有任何Javascript,而JS捆绑包则在后台下载。

  2. 由于light主题是默认主题,因此网站的静态版本将是light。

  3. Javascript加载,React的第一个渲染发生,并且Redux存储被初始化。根组件从中获取主题,localStorage树以深色主题重新渲染。

由于2到3之间的事件而发生闪烁。

我没有完全解决问题。但是,通过启用Gatsby的服务人员,我设法减轻了闪烁现象,使其更加不明显。Worker缓存Javascript捆绑包供下次访问,而从磁盘加载Javascript意味着闪烁将持续较短的时间,因为JS捆绑包已经可以执行了。