【问题标题】:How to deal with local storage and SSR?如何处理本地存储和 SSR?
【发布时间】:2020-11-28 10:28:36
【问题描述】:

我使用 useContext 和 React 创建了一个<ThemeProvider/>。在开发环境中一切正常。我可以将颜色传递给组件,并使用 useEffect 挂钩将选定的颜色主题存储在localStorage 中(可以通过单击按钮来选择主题颜色)。然后刷新后就可以从localStorage获取选中的主题颜色了。

我设法在 Netlify 上部署了网站,而我在开发环境中为本地存储编写的内容现在的行为方式不同了。我现在无法从本地存储中检索选定的主题颜色。

这里是一个代码sn-p:

const [state, setState] = useState({
       count: 0,
       mainColor: themesArray[getTheme()].mainColor,
       secondColor: themesArray[getTheme()].secondColor,
       thirdColor: themesArray[getTheme()].thirdColor,
       mainFilter: themesArray[getTheme()].mainFilter,
       secondFilter: themesArray[getTheme()].secondFilter,
       boxShadowRGB1: themesArray[getTheme()].boxShadowRGB1,
       boxShadowRGB2: themesArray[getTheme()].boxShadowRGB2,
       boxShadowRGB3: themesArray[getTheme()].boxShadowRGB3
   });

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

function getTheme() {
   if (typeof window === 'object' || typeof window !== 'undefined') {
       const savedTheme = JSON.parse(localStorage.getItem('theme'));
       return savedTheme || 0;
   } else return 0;
}

在 getTheme() 方法中,对于构建过程,我必须将localStorage 包装在一个条件中,因为窗口对象在构建期间不可用。我写了 return 0 (用于指向我的主题数组中的第一个主题),因为否则它返回 undefined 并且构建失败。问题是,在生产中,通过以这种方式编写它,我无法在刷新后检索选定的主题。但是在开发工具中,我可以看到我的主题项目存储有很好的价值。我对SSR一无所知,所以我有点迷茫,不知道如何编码。有人可以帮忙吗?

【问题讨论】:

  • SSR 是服务端渲染,它无法访问客户端存储(会话存储、本地存储、indexDb、webSql 等)。如果您在呈现服务器端时需要此信息,则必须以某种方式派生它或将其与您的请求一起发送。
  • @chalatum 你解决过这个问题吗?我也在使用 GatsbyJS,并尝试使用本地存储中的变量初始化状态挂钩值......但在本地和部署的站点中看到不同的行为:(

标签: reactjs local-storage gatsby server-side-rendering


【解决方案1】:

您可以在 video 中了解如何在 React 中使用带有 useEffect 钩子的本地存储。为了更好地理解 - 实际用法 - 查看我处理本地存储的简单愚蠢项目不使用任何 useEffect 挂钩 GitHub

【讨论】:

  • 感谢您提供这些链接,但不幸的是它们并没有太大帮助。视频看起来就像我在开发环境中应用的一样,效果很好。但它在生产环境中失败了。
  • 我认为您应该检查一下您在生产中使用的 NodeJS 和 React 版本。如果他们不匹配,你知道该怎么做......
【解决方案2】:

我相信您的代码已正确设置为 SSR 和 localStorage。这更像是一个关于使用 React 钩子触发重新渲染的问题。

我认为这就是它不加载您的主题的原因:

useEffect(() => {
  localStorage.setItem('theme', JSON.stringify(state.count));
  // no rerender triggered
}, [state.count]); 

您不会更改 useEffect 中的状态。您需要一些方法来触发重新渲染,以便您可以看到新主题。通过改变状态触发重新渲染:

useEffect(() => {
  localStorage.setItem('theme', JSON.stringify(state.count));
  // React rerenders on state change
  setState({
    ...state,
    count: newCount,
  });
}, [state.count]); 

您可以通过按下按钮或更改主题来传递newCount

这个关于强制重新渲染的question 可能会对您有所帮助。

【讨论】:

    猜你喜欢
    • 2012-12-10
    • 2019-07-03
    • 2017-05-31
    • 2022-01-03
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    相关资源
    最近更新 更多