在同构 Redux 应用程序中在哪里设置 cookie?

Posted

技术标签:

【中文标题】在同构 Redux 应用程序中在哪里设置 cookie?【英文标题】:Where to set cookie in Isomorphic Redux Application? 【发布时间】:2016-04-21 16:14:52 【问题描述】:

我有 3 个关于 redux 和同构应用的一般性问题:

在客户端和服务器之间共享“运行时”数据的最佳方式是什么? 例如,当用户登录远程 API 时,我将会话对象存储在 cookie 中。这样,下一次客户端请求我的前端,前端服务器可以读取 cookie 并使用它的前一个会话初始化 redux 存储。这样做的缺点是客户端必须在启动时验证/使会话无效(例如,在根组件的 componentDidMount 中)。 我应该请求会话服务器端而不是从 cookie 中读取它吗? 我应该在哪里执行 cookie 存储操作,在 action creators 中还是在 reducer 中? 我应该将 cookie 存储在处理用户会话的 reducer 中吗? 我应该在哪里执行重定向用户的操作(通过 react-router)? 我的意思是当我的用户成功登录时,我应该从哪里发送重定向操作(从 loginActionCreator 一旦登录承诺解决了吗?,其他地方?)

提前致谢。

【问题讨论】:

【参考方案1】:

我设法获得了一个非常简洁的应用程序结构。 以下是我对每个问题的发现:

我只在我的客户端和前端服务器之间通过 cookie 共享 API 服务器令牌。每次客户端请求该站点。前端服务器调用 API 服务器来验证会话。如果这些服务器在同一个网络上,它真的很快(

存储 cookie 的动作在我的动作创建者中。正如 Ethan Clark 所说,我们必须保持 reducer 的纯净。它更容易测试。

一旦用户通过身份验证,我仍然会在我的登录创建器中发送重定向。我想测试比在组件或其他地方的承诺解决后调度动作更容易。

事实上,牢记这一点可以让我们拥有一个非常容易测试的应用(除了那些你必须有大量间谍的动作创建者)。

希望对某人有所帮助。

感谢参与。

【讨论】:

你有 GitHub 存储库或类似的例子吗?【参考方案2】:

问题2:你应该在你的action creator中执行cookie存储。 Reducers 必须保持纯函数。

非常抱歉,我不知道 1 和 3 的答案,但我希望这会有所帮助!

【讨论】:

感谢您的回答。你有解释原因的链接吗? 我认为这是因为减速器需要保持同步。我找不到我读过的关于这个的原始帖子,但这涉及到它:github.com/rackt/redux/issues/291【参考方案3】:

您可能应该将您的问题分成三个不同的堆栈溢出问题,因为它们都有点不同。

我同意 Ethan 的观点,你的减速器应该是纯净的,没有副作用。无论如何,这就是目标(又名最佳实践)。然而,Ben Nadel 一直在探索这些问题,并建议创建一个工作流层来管理业务逻辑,而不是把这个负担放在商店身上。您应该查看他的Managing Locally Cached Data with Redux in AngularJS 文章以了解更多信息。

【讨论】:

感谢您的回答。我阅读了 Ethan Clark 的链接,非常有趣。我从减速器中删除了所有副作用,并将它们放入我的动作创建器中。我将阅读您的文章并将我的问题分成 3 个堆栈溢出问题。【参考方案4】:

Cookies 是同步的——你可以 hydra 并订阅你的 store,或者在将 reducer 添加到 createStore 之前创建一个元 reducer。以下是以下两者的快速示例:

//first option
 const Cookie = require('js-cookie');
const loadState = (key) => Cookie.getJSON(key);
const saveState = (nextState, key) => Cookie.set(key, nextState);
const persistedState = loadState('todos');
const store = createStore(
  todoApp,
  persistedState
);

store.subscribe(throttle(() => 
  saveState(
    todos: store.getState().todos,
  , 'todos');
, 1000));

//second option - meta reducer
// usage  
    const Cookie = require('js-cookie');

    export function cookieMeta (
      key: string,
      reducer: any,
      expiry: Date | number = 365,
      path: string = '/',
      domain: string = window.location.hostname): Function 
      return function(state: any, action: any): any 
        let nextState = reducer(state, action);
        let cookieState = Cookie.getJSON(key);

        if (action.type.includes('DELETE')) 
          Cookie.remove(key);
         else if (!nextState && cookieState || action.type === '@@redux/INIT') 
          nextState = cookieState;
         else if (nextState && nextState !== cookieState) 
            Cookie.set(key, nextState,  expires: expiry, path: path, domain: domain, secure: process.env.local );
        
        return nextState;
      ;
    ;
// how to implement the meta reducer
import  todos  from './todos';
import  cookieMeta  from './middleware/cookieMeta';
export function TODOS_REDUCER (state: any, action: any) 
    return cookieMeta('todos', todos)(state, action);

export const todoApp = combineReducers( todos: TODOS_REDUCER  )

【讨论】:

以上是关于在同构 Redux 应用程序中在哪里设置 cookie?的主要内容,如果未能解决你的问题,请参考以下文章

在同构应用程序中使用 redux

在同构的 Redux 应用程序中,最好的做法是保持 API 调用较小,还是一次性发送所有信息?

具有代码拆分和延迟加载减速器的同构 Redux

在objective-c中在哪里设置窗口大小iOS?

在 Alpine linux 中在哪里设置系统默认环境变量?

在 mysql 中在哪里设置 IN 条件(父表或子表)