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

时间:2015-08-07 22:33:30

标签: javascript reactjs flux redux

我一直在使用React + Flux应用程序中的乐观更新并看到两件事:

  1. 如果用户在存在某些未完成的操作时尝试关闭窗口,会发生什么情况。例如,在Facebook中,即使没有真正持久化,也会在墙上显示一条消息(这是乐观更新所做的,对用户来说响应更快的应用程序)。但是,如果用户在墙上张贴并立即关闭应用程序(在注销或窗口关闭时),帖子可能会失败并且他不会收到警报。
  2. 我不喜欢Stores管理自己的实体(例如消息)的想法以及为persiste消息触发的动作的情况(加载,成功,失败?)。它混合了一些东西。
  3. 因此,我在此处工作并创建 ActionStore 来管理组件触发的操作的状态。 Here is源代码和here is现场演示。

    它或多或少都是这样的:

    1. 组件层次结构的根(redux中的容器)获取新动作的nextId并将其传递给他的孩子,如道具(这很难看)。
    2. 子组件触发一个动作:它保留actionId,以便在之后向商店询问并调用动作创建者。
    3. 动作创建者创建一个新的Action并将一个函数返回给中间件。
    4. 从Action返回的函数使用API​​调用创建一个新的Promise,并调度XX_START类型的操作。
    5. ActionStore会收听XX_START操作并保存。
    6. 子组件接收新状态并找到具有已保存ID的操作,并询问当前情况:加载,成功或失败。
    7. 我这样做主要是为了分离"实体的状态"从操作的状态开始,但允许使用相同的有效负载进行重新触发操作(如果服务器暂时关闭或用户松动信号,当我们收到500响应状态时,这可能很有用。)

      此外,拥有一系列操作可以在用户注销或关闭窗口之前轻松询问它们是否为待处理操作。

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

      这是一个可行的选择创建一个ActionStore还是我打破了一些Redux / Flux基础? 这可能会结束使用React Hot Reloading和Time travel的可能性吗?

      你应该毫不怜悯地回答,我可能已经完成了许多丑陋的事情,但我正在学习React / Redux。

1 个答案:

答案 0 :(得分:23)

对于未来可能有点困惑的读者:我们不再将这些功能称为“商店”:我们称之为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);
  }
}

您可以像普通的减速器一样使用它:

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字段中的所有操作。

同样,这本身并不是很有用,但您可以看到如何实现这样的高阶减速器:

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

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

更新:根据OP的评论,redux-optimist似乎正是如此。