React Redux:Reducer是否包含任何逻辑

时间:2017-11-10 16:40:03

标签: reactjs react-native redux react-redux

我有一个带有添加,更新和删除案例的购物车减速器功能。我还在redux商店中有一个产品阵列。如果有两个项目添加到产品数组中,而不是有两个项目,我会增加数量值。我的主要问题是,如果Reducer包含任何逻辑,即确定产品数组是否已包含确切的产品,并且只返回产品数量的更新,或者应该在显示组件内检查现有产品并添加新产品产品或更新数量?

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
  }
}

4 个答案:

答案 0 :(得分:13)

the Redux FAQ entry on splitting logic between reducers and action creators

  

对于缩减器或动作创建者应该采用哪些逻辑,没有一个明确的答案。一些开发人员更喜欢拥有“胖”动作创建器,其中“瘦”缩减器只是简单地将动作中的数据接收并盲目地将其合并到相应的状态中。其他人试图强调保持尽可能小的动作,并最小化动作创建者中getState()的使用。 (出于这个问题的目的,其他异步方法,例如sagas和observables属于"动作创建者"类别。)

     

将更多逻辑放入减速机有一些潜在的好处。动作类型可能更具语义性和更有意义(例如" USER_UPDATED"而不是" SET_STATE")。此外,在reducer中使用更多逻辑意味着更多功能将受到时间旅行调试的影响。

     

这个评论很好地总结了二分法:

     
    

现在,问题是在动作创建器中放置什么,以及在reducer中,fat和thin动作对象之间的选择。如果将所有逻辑放在动作创建器中,最终会生成基本上声明状态更新的胖动作对象。 Reducers变得纯粹,愚蠢,添加 - 删除它,更新这些功能。它们很容易构成。但是你的业务逻辑并不多。如果你在reducer中加入了更多的逻辑,你最终会得到漂亮的瘦动作对象,大部分数据逻辑都集中在一个地方,但是你的reducer更难以编写,因为你可能需要来自其他分支的信息。你最终会得到大型减速器或减速器,这些减速器或减速器会从该州的较高位置获得额外的参数。

  

我还写了my own thoughts on "thick and thin" reducers

  

在行动创造者中加入更多逻辑与在减速器中加入更多逻辑之间存在有效的权衡。我最近看到的一个好处是,如果你在减速器中有更多的逻辑,这意味着如果你是时间旅行调试(这通常是一件好事),可以重新运行更多的东西。

     

我个人倾向于同时在两个地方放置逻辑。我写动作创建者需要花时间来确定是否应该分派动作,如果是,那么内容应该是什么。但是,我也经常编写相应的reducers来查看动作的内容并执行一些复杂的状态更新作为响应。

答案 1 :(得分:3)

当然!减速器应该是纯函数,因此逻辑也必须是纯粹的。这意味着应该没有副作用。副作用包括(但不限于):

  • 数据库请求/存储
  • 文件IO
  • REST /异步调用
  • 全球或外部突变
  • 任何类型的数据突变

因此,reducer不应该改变进入的状态,而是返回仅对副本进行修改的副本,如果是这样的话。不可变值(如字符串,数字,未定义等)可以按原样返回,因此可以声明,如果它没有被修改。但是,如果您需要对任何输入进行任何更改,则需要返回新副本或新值。

关于从reducer调用的逻辑,只要所有代码都符合这些要求,那么你就符合Redux模式。

不幸的是,当任何给定的代码都有副作用(其他语言都有)时,JavaScript没有办法确定,所以你应该知道你在调用什么。

如果你失败会破坏Redux吗?不会。但事情可能与您(或Flux / Redux开发人员)所期望的完全无关。

答案 2 :(得分:1)

不,它们不应该包含逻辑


  • 组件:应将现有的redux数据作为操作的依赖项传递
  • 操作:收集尽可能多的数据,适用于尽可能多的减速器
  • 减速器:提取动作对象片段进行存储
  • *副作用::后续动作侦听器/调度程序,当您不想在发出初始事件之前等待时有用(传奇是基于订阅的,thunk是声明性链)

经验法则是尽一切努力

急切的操作(提前返回,快速失败,提升状态等)阐明了是否同时存在特定的依赖关系,并使决策变得容易

急切的操作符合“关注点分离”和模块化,声明性,有状态,务实,易读代码的简单主题:声明依赖项,操作和返回

所有其他事情都与排序有关,应该尽快完成

减速器是您最后想要“做”任何事情的地方。实际上,这是一次“返回”,应仅从动作对象中选择数据

答案 3 :(得分:0)

考虑一下您可能要在中间件中执行的操作...如果将所有逻辑都放入化简器中,则中间件中的记录将不会应用业务逻辑。

  1. 派遣(新的UpdatePerson(人))
  2. 运行中间件并拦截UpdatePerson操作
  3. 减速器-更新人的年龄值

如果要说,将记录保存在商店中,那么reducer逻辑将运行得太晚,并且您将无法以中间件中要求的状态访问已更改的记录。