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

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

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

提前致谢。

【问题讨论】:

    标签: javascript node.js reactjs redux isomorphic-javascript


    【解决方案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  })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-19
      • 1970-01-01
      • 2012-02-04
      • 2018-06-19
      • 1970-01-01
      • 2022-08-13
      • 2018-11-10
      • 2016-08-10
      相关资源
      最近更新 更多