首页 > 解决方案 > 使用带有 SSR (Next.js) 应用程序的 localStorage 持久化 React 状态时遇到问题

问题描述

我正在制作的应用程序具有可自定义的设置。我想加载默认设置,然后当用户进行任何更改时,自定义设置将存储在 localStorage 中。现在下次用户回来时,我们将从他们的 localStorage 加载设置。

我正在像这样使用 React 上下文...

    const SettingsContextProvider = (props: any) => {
        const [settings, setSettings] = useState(getSettings());

        useEffect(() => {
            localStorage.setItem('settings', JSON.stringify(settings))
        }, [settings]);

        return (...some jsx...);
    }

然后 getSettings()...

   getSettings() {
       // get from local storage
       if (process.browser) {
           const localSettings = localStorage.getItem('settings');
           if (localSettings) return JSON.parse(localSettings );
       }

       // fall back to default settings
       return "Something else";
   }

我遇到的问题是服务器端负载(在节点端),我们没有本地存储(这就是我检查的原因process.browser),所以它回退到默认设置。然后当它到达浏览器时,它似乎getSettings()再次调用,在这种情况下,我们确实有本地存储,它从那里加载。

那行得通,但后来我得到一个错误

Text content did not match. Server: "Something else" Client: "Something custom"

所以我知道服务器与客户端不匹配并且对此感到不安。我明白为什么会这样,但我不知道如何解决它。也许我需要实现减速器或使用 cookie?

有没有人遇到过这个?

如果有帮助,我很乐意分享我的完整回购代码。

标签: javascriptreactjsnext.js

解决方案


我对反应相当满意,但几乎从未在我自己的代码中使用过反应钩子。

但是,我觉得我不会将 localStorage 的更新放入这样的useEffect函数中(我可能完全错了)。

因此,首先,我会检查该useEffect函数是否在您期望的时候被调用。

然后,我会写一个函数

 const updateSettings = (newSettings) => {
      localStorage.setItem('settings', JSON.stringify(newSettings))
      setSettings(newSettings);
 }

并使用该updateSettings函数传递给组件。

但是,我可能完全不在那儿,就像我说的那样,我不使用反应钩子,只有理论上的理解。


推荐阅读