我一直在使用React Flux应用程序中的乐观更新,并看到两件事:
-
如果用户在存在一些未完成的操作时尝试关闭窗口会发生什么 . 例如在Facebook中,即使没有真正持久化,也会在墙上显示一条消息(这是乐观更新所做的,对用户来说响应更快的应用程序) . 但是,如果用户在墙上发布并立即关闭应用程序(在注销或窗口关闭时),帖子可能会失败并且他不会收到警报 .
-
我不喜欢Stores管理自己的实体(例如消息)的想法以及为persiste消息触发的动作的情况(加载,成功,失败?) . 它混合了一些东西 .
因此,我在此工作并创建一个 ActionStore 来管理由组件触发的操作的状态 . Here is源代码和here is现场演示 .
它的工作方式或多或少如下:
-
组件层次结构的根(redux中的容器)获取新操作的nextId并将其传递给他的子项,如props(这很难看) .
-
子组件触发一个动作:它保持actionId以便在之后向商店询问并调用动作创建者 .
-
动作创建者创建一个新的Action并将一个函数返回给中间件 .
-
从Action返回的函数使用API调用创建一个新的Promise,并调度类型为XX_START的操作 .
-
ActionStore收听XX_START操作并保存 .
-
子组件接收新状态并找到具有已保存ID的操作,并询问当前情况:加载,成功或失败 .
我这样做主要是为了将“实体”的状态与动作的状态分开,但允许具有相同有效负载的重新触发操作(如果服务器暂时关闭或者如果我们收到500响应状态,这可能很有用用户松动的信号) .
此外,拥有操作存储允许在用户注销或关闭窗口之前轻松询问它们是否是待处理操作 .
注意:我正在使用针对Rest API的单应用程序页面Web应用程序,我不认为在服务器端呈现时使用它
这是一个可行的选择创建一个ActionStore还是我打破了一些Redux / Flux基础?这可能会结束使用React Hot Reloading和Time travel的可能性吗?
你应该毫不留情地回答,我可能做了一堆丑陋的事情,但我正在学习React / Redux .
1 回答
对于未来可能有点困惑的读者:我们不再将这些功能称为“商店”:我们称之为reducers . 所以问题是关于a reducer remembering actions .
就个人而言,我不喜欢你在那里建议的方法 . 您将逻辑放入操作并使用继承 . 相反,Redux将行为规定为没有逻辑的普通对象 . 他们不应该“知道”如何更新某些状态,他们不应该持有它 - 相反,他们应该描述发生的事情 .
我认为在Redux中实现乐观更新的方法类似于你如何implement Undo in Redux,而这反过来又受到Elm architecture的启发 . 这个想法是你应该编写一个带有reducer(和一些选项)的函数并返回一个reducer:
你可以像普通的reducer一样使用它:
现在它只是将状态和动作传递给它包装的
reducer
,但它也可以“记住”动作:现在它累积了
history
字段中的所有操作 .同样,这本身并不是很有用,但您可能会看到如何实现这样的更高阶的减速器:
通过其ID跟踪待处理的异步操作,并在看到
status: 'request'
的操作时开始记录历史记录;当它收到
status: 'done'
的动作时,重置历史记录;当它收到
status: 'fail'
的操作时,调整历史记录以不包括status: 'request'
和 re-runs the reducer to re-calculate the present state as if the request never happened. 的初始操作当然我没有提供实现,但是这应该让您了解如何以Redux方式实现乐观更新 .
Update: as per the OP's comment, redux-optimist seems to do exactly that.