React/Redux 服务端渲染初始状态

Posted

技术标签:

【中文标题】React/Redux 服务端渲染初始状态【英文标题】:React/Redux server side rendering initial state 【发布时间】:2016-04-03 19:46:17 【问题描述】:

我有一个 React/Redux 应用程序,它在本地存储中跟踪用户的身份验证状态。该应用程序还设置为使用服务器端渲染。我在呈现初始应用程序状态时遇到了问题。我的服务器创建一个新商店并发出 SET_INITIAL_STATE 操作。客户端的这个初始操作读取 localStorage 并将经过身份验证的信息传递给我的减速器。但是,服务器不知道此登录状态,因为我使用位于本地存储中的无状态 JWT 进行身份验证。

由于此时服务器和客户端不同步,我收到此错误:

React 尝试在容器中重用标记,但校验和无效。这通常意味着您正在使用服务器渲染,并且在服务器上生成的标记不是客户端所期望的。 React 注入了新的标记来补偿哪些工作,但是您已经失去了服务器渲染的许多好处。相反,请弄清楚为什么在客户端或服务器上生成的标记不同:

这是有道理的,因为服务器正在尝试呈现未经身份验证的状态。

设置这个完全依赖于客户可以访问的东西的初始状态的公认标准或实践是什么?

【问题讨论】:

如果实际上只有客户端可以访问它,那么您就不能(至少,我想不出一个好方法)。您可以做的最好的事情是在服务器上呈现一个非常骨架的应用程序(或其他一些对经过身份验证的用户不太合适的应用程序版本 - 例如,您可能具有服务器呈现的“加载”状态或类似状态),以相同的方式初始化客户端应用程序,然后然后根据令牌重新渲染 - 但这基本上就是您已经在做的事情(除了警告:) 【参考方案1】:

我发现 OP 是对的,cookie 存储是最好的选择。如果您将 react、redux 和 express 用于通用应用程序,则适用于我的选项是 https://github.com/eXon/react-cookie。

基本上:

您可以在服务器端代码中使用:

  import cookie from 'react-cookie';

  function handleRender(req, res) 
      cookie.setRawCookie(req.headers.cookie);

      // Create new Redux store instance
      const store = createStore(rootReducer, 
          username: cookie.load('username') || '',
          accessLevel: cookie.load('accessLevel') || userRoles.public,
      );

      //other react/redux/express related code
  

在您的 react 应用程序中,在组件内部,您可以直接保存 cookie:

  import cookie from 'react-cookie';

  //first parameter is anything you want, second is the data you want to save
  cookie.save( 'username', username );
  cookie.save('accessLevel', accessLevel);

如果你想存储一个对象,就像我做的那样,你可以传入JSON.stringify(your object)。 cookie.load 会自动为你解析。

在我的代码中,我从操作中调用了 cookie.save,但您可以直接在组件或您拥有的任何抽象中调用它。

【讨论】:

【参考方案2】:

我找到了一个可行的解决方案。

不幸的是,诀窍是将经过身份验证的状态存储在 cookie 中,以便会话状态在请求时自动发送到服务器。

【讨论】:

你能发布你完成这个的代码/方法吗?

以上是关于React/Redux 服务端渲染初始状态的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React/redux 中进行服务器端渲染?

使用 redux 和 react 进行异步服务器端渲染

react + redux + saga +服务器端渲染+如何停止服务器端渲染页面的额外ajax调用?

如何在逻辑上结合 react-router 和 redux 进行客户端和服务器端渲染

React dva 的使用

服务端渲染