如何确保使用React的第一个渲染具有localStorage的值?

时间:2019-07-02 14:12:03

标签: javascript reactjs frontend

我的网站有浅色和深色主题。默认主题为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中的设置值?

2 个答案:

答案 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应用之前加载。

加载网站的过程如下:

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

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

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

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

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