javascript - 用于乐观更新的操作存储是 Redux/Flux 中的一个好方法吗?

标签 javascript reactjs flux redux

我一直在 React+Flux 应用程序中进行乐观更新,并看到了两件事:

  1. 如果用户在存在某些未完成的操作时尝试关闭窗口,会发生什么情况。例如,在 Facebook 中,即使没有真正持久化,消息也会出现在墙上(这就是乐观更新的作用,对用户来说是一个响应更快的应用程序)。但是,如果用户在留言墙上发帖并立即关闭应用程序(注销或窗口关闭时),则发帖可能会失败,并且他不会收到提醒。
  2. 我不喜欢商店管理自己的实体(例如消息)的想法以及为持久化消息而触发的操作的情况(加载、成功、失败?)。它混合了东西。

因此,我致力于此并创建一个 ActionStore 来管理组件触发的操作的状态。 Here is源代码和here is现场演示。

它的工作原理或多或少是这样的:

  1. 组件层次结构的根(redux 中的容器)获取新操作的 nextId 并将其像 props 一样传递给他的子级(这很难看)。
  2. 子组件触发一个操作:它保留 actionId,以便在之后将其请求到存储并调用操作创建者。
  3. Action 创建者创建一个新的 Action 并向中间件返回一个函数。
  4. 从 Action 返回的函数通过 API 调用创建一个新的 Promise,并分派(dispatch) XX_START 类型的操作。
  5. ActionStore 监听 XX_START 操作并保存它。
  6. 子组件接收新状态并查找具有已保存 ID 的操作并询问当前情况:加载、成功或失败。

我这样做主要是为了将“实体”的状态与操作的状态分开,但也允许使用相同的负载重新触发操作(如果服务器暂时处于响应状态,当我们收到 500 响应状态时,这可能很有用)下降或用户失去信号)。

此外,拥有操作存储可以在用户注销或关闭窗口之前轻松询问它们是否正在等待操作。

注意:我正在使用针对 Rest API 的单应用程序页面 Web 应用程序,我不认为在服务器端渲染上使用它

创建 ActionStore 是一个可行的选择,还是我破坏了一些 Redux/Flux 基础? 这可能会结束使用 React 热重载和时间旅行的可能性吗?

你应该毫不留情地回答,我可能做了很多丑陋的事情,但我正在学习 React/Redux。

最佳答案

对于可能有点困惑的 future 读者:我们不再称这些函数为“存储”:我们称它们为 reducers 。所以问题是关于a reducer remembering actions .

我个人不喜欢你在那里建议的方法。您将逻辑放入操作中并为此使用继承。相反,Redux 将操作规定为没有逻辑的普通对象。他们不应该“知道”如何更新某些状态,也不应该保留它 - 相反,他们应该描述发生了什么。

我认为在 Redux 中实现乐观更新的方法类似于 implement Undo in Redux ,其灵感又来自 Elm architecture 。这个想法是,您应该编写一个函数,它接受一个 reducer (和一些选项)并返回一个 reducer :

function optimistic(reducer) {
  return function (state, action) {
    // do something?
    return reducer(state, action);
  }
}

你可以像普通的 reducer 一样使用它:

export default combineReducers({
  something: optimistic(something) // wrap "something" reducer
})

现在它只是将状态和操作传递给它包装的reducer,但它也可以“记住”操作:

function optimistic(reducer) {
  return function (state = { history: [] }, action) {
    // do something with history?
    return {
      history: [...state.history, action],
      present: reducer(state.history[state.history.length - 1], action)
    };
  }
}

现在它会累积 history 字段中的所有操作。

同样,这本身并不是很有用,但您可能会看到如何实现这样的高阶 reducer :

  • 通过 ID 跟踪待处理的异步操作,并在看到 status: 'request' 的操作时开始记录历史记录;
  • 当它收到状态为“完成”的操作时,重置历史记录;
  • 当它收到 status: 'fail' 的操作时,调整历史记录以不包含 status: 'request' 的初始操作并重新运行reducer来重新计算当前状态,就好像请求从未发生过一样。

当然,我没有提供实现,但这应该让您了解如何以 Redux 方式实现乐观更新。

更新:根据OP的评论,redux-optimist似乎正是这样做的。

关于javascript - 用于乐观更新的操作存储是 Redux/Flux 中的一个好方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31887573/

相关文章:

javascript - 窗口之间的 EXTJS 值

javascript - 如何确保我的第一个 React 渲染具有来自 localStorage 的值?

javascript - 在 React 中,组件如何将自身作为参数传递?

javascript - Flux:将 Action 与 Action 创建者分开的常见做法

javascript - Kendo UI 网格中滚动事件的回调

javascript - 使用跨度,其他文本在下一行

javascript - 如何使图像高度适合模态 div

reactjs - 类型 'string' 不可分配给类型 '"菜单“| "selectedMenu"| 未定义”

spring-boot - SSEemitter 与 Spring Boot 中的 Flux

javascript - 更改输入框的值状态时出错