在同构 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 应用程序中,最好的做法是保持 API 调用较小,还是一次性发送所有信息?