在Redux/Flux中,用于优化更新的操作存储区是一个好方法吗? [英] A Store of Actions for optimistic updates is a good approach in Redux/Flux?

查看:89
本文介绍了在Redux/Flux中,用于优化更新的操作存储区是一个好方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been working with optimistic updates in a React+Flux application and saw two things:

  1. 如果存在某些未完成的操作,而用户试图关闭窗口,会发生什么情况.例如,在Facebook中,即使不是真正持久存在,消息也会出现在墙上(这就是乐观更新所做的事情,这是对用户更敏感的应用程序).但是,如果用户在墙上发贴并立即关闭应用程序(在注销或关闭窗口时),则贴发可能会失败,并且不会收到警告.
  2. 我不喜欢商店管理自己的实体(例如消息)的想法,并且因持久性消息(加载,成功,失败?)而触发的操作情况.它混合了东西.

因此,我要进行此工作,并创建一个 ActionStore 来管理由组件触发的动作的状态. 这里是源代码和

So I work on this and create an ActionStore to manage the state of the actions triggered by the components. Here is the source code and here is a live demo.

它或多或少像这样工作:

It works more or less like this:

  1. 组件层次结构的根(redux中的容器)获取一个新动作的nextId并将其像props一样传递给他的孩子(这很丑).
  2. 子组件触发一个动作:它保留actionId以便以后向商店询问并调用动作创建者.
  3. 动作创建者创建一个新的动作,并将一个函数返回给中间件.
  4. 从Action返回的函数使用API​​调用创建一个新的Promise并调度类型为XX_START的动作.
  5. ActionStore监听XX_START动作并保存.
  6. 子组件收到新状态,并找到具有已保存ID的操作,并询问其当前情况:正在加载,成功或失败.

我这样做主要是为了将实体"的状态与动作的状态分开,但是也允许使用相同的有效负载进行重新触发动作(如果服务器是临时的,当我们收到500个响应状态时,这可能会很有用向下或用户松动的信号).

I've done this mainly for separate the state of the "entities" from the state of the actions, but allows retrigger actions with the same payload too (this could be useful when we receive 500 response status if the server is temporarly down or if the user loose signal).

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

Also, having an store of actions allows to easily ask if they are pending actions before the user logout or close the window.

注意:我正在针对Rest API使用单个应用程序页面Web应用程序,我不认为在服务器端渲染中使用此功能

Note: I'm working with a Single Application Page web app against a Rest API, I'm not think to use this on server-side rendering

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

It's a viable option create a ActionStore or I'm breaking some Redux/Flux foundations? This could end the posibility of use React Hot Reloading and Time traveling?

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

You should answer with no mercy, I've probably done a bunch of ugly things but I'm learning React/Redux.

推荐答案

对于可能有些困惑的未来读者:我们不再将这些函数称为存储":我们将它们称为减速器记忆动作.

To the future readers who might be a little bewildered: we don't call these functions "stores" anymore: we call them reducers. So the question is about a reducer remembering actions.

我个人不喜欢您在此处建议的方法.您正在将逻辑付诸行动并为此使用继承.相反,Redux将动作规定为无逻辑的普通对象.他们不应该知道"如何更新某些状态,也不应该持有状态,而是应该描述发生了什么.

Personally I don't like the approach you're suggesting there. You're putting logic into actions and using inheritance for this. On the contrary, Redux prescribes actions to be plain objects without logic. They shouldn't "know" how to update some state, and they shouldn't hold it—instead, they should describe what happened.

我认为在Redux中实现乐观更新的方法类似于您在Redux中实现撤消的方式,反过来受到 Elm体系结构的启发.这个想法是,您应该编写一个带有一个reducer(和一些选项)并返回一个reducer的函数:

I think the approach for implementing optimistic updates in Redux is similar to how you'd implement Undo in Redux, which in turn is inspired by Elm architecture. The idea is that you should write a function that takes a reducer (and some options) and returns a reducer:

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

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

You'd use it just like a normal reducer:

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

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

Right now it just passes the state and action to the reducer it wraps, but it can also "remember" actions:

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字段中累积所有操作.

Now it accumulates all actions in the history field.

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

Again, this by itself is not very useful, but you can probably see how you can implement such higher order reducer that:

  • 通过其ID跟踪待处理的异步操作,并在看到使用status: 'request'的操作时开始记录历史记录;
  • 当它收到使用status: 'done'进行的操作时,将重置历史记录;
  • 当它接收到带有status: 'fail'的动作时,将历史记录调整为不包括带有status: 'request'的初始动作,并且重新运行化简器以重新计算当前状态,就好像请求从未发生过. /strong>
  • keeps track of pending async actions by their IDs and starts recording the history when it sees an action with status: 'request';
  • when it receives an action with status: 'done', resets the history;
  • when it receives an action with status: 'fail', adjusts the history to not include the initial action with status: 'request' and re-runs the reducer to re-calculate the present state as if the request never happened.

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

Of course I haven't provided the implementation, but this should give you an idea of how to implement optimistic updates in a Redux way.

更新:根据OP的评论, redux-optimist 似乎恰好做到了.

Update: as per the OP's comment, redux-optimist seems to do exactly that.

这篇关于在Redux/Flux中,用于优化更新的操作存储区是一个好方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆