我有一个带有添加,更新和删除案例的购物车减速器功能。我在redux商店中也有一个产品数组。当有两个项目添加到产品数组时,我没有增加两个项目,而是增加了数量值。我的主要问题是,化简器是否应包含任何逻辑,即确定产品数组是否已包含确切的产品并仅返回产品数量的更新,还是应在表示性组件中处理此行为以检查现有产品并添加新的产品或更新数量?
function CartReducer (state = initialState, action) { switch (action.type) { case AddToCart: return { ...state, products: [...state.products, action.product], totalPrice: state.totalPrice += (action.price * action.quantity) } case RemoveItemCart: return { ...state, products: [ ...state.products.slice(0, action.index), ...state.products.slice(action.index + 1) ] } case UpdateItemQuantity: return { ...state, products: state.products.map((product, index) => { if (index === action.index) { return Object.assign({}, product, { quantity: action.quantity }) } return product }) } default: return state } }
根据Redux FAQ条目中关于化简和动作创建者之间的逻辑划分的内容:
对于在化简器或动作创建器中应该采用哪些逻辑,尚无一个明确的答案。一些开发人员更喜欢使用“胖”动作创建者,并使用“瘦”精简器将动作中的数据简单地盲目合并为相应的状态。其他人则试图强调使动作尽可能的小,并最小化动作创建者中getState()的使用。(出于这个问题的目的,其他异步方法(例如sagas和observables属于“动作创建者”类别)。) 将更多的逻辑放入化简器有一些潜在的好处。动作类型可能更具语义和意义(例如,“ USER_UPDATED”而不是“ SET_STATE”)。另外,在reducer中具有更多的逻辑意味着更多的功能将受到时间旅行调试的影响。 此评论很好地总结了二分法: 现在,问题是要在动作创建者中放置什么,在减速器中放置什么,在胖瘦对象之间进行选择。如果将所有逻辑放入动作创建者中,最终将得到胖动作对象,这些对象基本上声明了对该状态的更新。减速器变得纯净,笨拙,添加,删除,更新这些功能。它们将很容易组成。但是您的业务逻辑并不多。如果在化简器中添加更多的逻辑,最终会得到漂亮的,瘦小的动作对象,大多数数据逻辑都集中在一个地方,但是化简器很难编写,因为您可能需要其他分支的信息。最终,您将得到大型化简器或化简器,这些化简器会从状态更高的子级获取其他参数。
对于在化简器或动作创建器中应该采用哪些逻辑,尚无一个明确的答案。一些开发人员更喜欢使用“胖”动作创建者,并使用“瘦”精简器将动作中的数据简单地盲目合并为相应的状态。其他人则试图强调使动作尽可能的小,并最小化动作创建者中getState()的使用。(出于这个问题的目的,其他异步方法(例如sagas和observables属于“动作创建者”类别)。)
将更多的逻辑放入化简器有一些潜在的好处。动作类型可能更具语义和意义(例如,“ USER_UPDATED”而不是“ SET_STATE”)。另外,在reducer中具有更多的逻辑意味着更多的功能将受到时间旅行调试的影响。
此评论很好地总结了二分法:
现在,问题是要在动作创建者中放置什么,在减速器中放置什么,在胖瘦对象之间进行选择。如果将所有逻辑放入动作创建者中,最终将得到胖动作对象,这些对象基本上声明了对该状态的更新。减速器变得纯净,笨拙,添加,删除,更新这些功能。它们将很容易组成。但是您的业务逻辑并不多。如果在化简器中添加更多的逻辑,最终会得到漂亮的,瘦小的动作对象,大多数数据逻辑都集中在一个地方,但是化简器很难编写,因为您可能需要其他分支的信息。最终,您将得到大型化简器或化简器,这些化简器会从状态更高的子级获取其他参数。
我还对“厚而薄”的减速器写下了自己的想法:
在动作创建者中放置更多逻辑与在化简器中放置更多逻辑存在有效的权衡。我最近看到的一个好处是,如果您在reducer中具有更多的逻辑,则意味着如果进行时间旅行调试,则可以重新运行更多的东西(通常这是一件好事)。 我个人倾向于同时将逻辑放在这两个地方。我写了一些动作创建者,这些动作创建者花时间确定是否应该分派动作,如果需要,则确定应该包含的内容。但是,我也经常编写相应的化简器,以查看动作的内容并作为响应执行一些复杂的状态更新。
在动作创建者中放置更多逻辑与在化简器中放置更多逻辑存在有效的权衡。我最近看到的一个好处是,如果您在reducer中具有更多的逻辑,则意味着如果进行时间旅行调试,则可以重新运行更多的东西(通常这是一件好事)。
我个人倾向于同时将逻辑放在这两个地方。我写了一些动作创建者,这些动作创建者花时间确定是否应该分派动作,如果需要,则确定应该包含的内容。但是,我也经常编写相应的化简器,以查看动作的内容并作为响应执行一些复杂的状态更新。
更新
从2020年开始,我们特别建议 在减速器中加入尽可能多的逻辑 :
尽可能 尝试将用于计算新状态的尽可能多的逻辑放入适当的reducer中,而不是放在准备和分派操作的代码中 (例如单击处理程序)。这有助于确保可以轻松地测试更多实际的应用逻辑,可以更有效地使用时间旅行调试,并有助于避免可能导致突变和错误的常见错误。 在有效情况下,应首先计算部分或全部新状态(例如生成唯一ID),但应将其保持在最低水平。
尽可能 尝试将用于计算新状态的尽可能多的逻辑放入适当的reducer中,而不是放在准备和分派操作的代码中 (例如单击处理程序)。这有助于确保可以轻松地测试更多实际的应用逻辑,可以更有效地使用时间旅行调试,并有助于避免可能导致突变和错误的常见错误。
在有效情况下,应首先计算部分或全部新状态(例如生成唯一ID),但应将其保持在最低水平。