我有一个cart reducer功能,可以添加、更新和删除 case .我在reduxstore 里也有一个产品array.

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

推荐答案

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

对于减速机或动作创建者中到底应该包含哪些逻辑片段,没有一个明确的答案.一些开发人员更喜欢有"胖"的动作创建者,而"瘦"的还原器只需在动作中获取数据,然后盲目地将其合并到相应的状态.其他人则试图强调让动作尽可能小,并尽量减少动作创建者中getState()的使用.(就这个问题而言,其他异步方法,如sagas和Observable,属于"action creator"类别.)

把更多的逻辑放进你的简化程序中有一些潜在的好处.动作类型可能更具语义,更有意义(比如"用户更新"而不是"设置状态").此外,在减速机中有更多的逻辑意味着更多的功能将受到时间旅行调试的影响.

这一 comments 很好地总结了这种二分法:

现在,问题是在action creator中放置什么,在reducer中放置什么,在胖动作对象和瘦动作对象之间进行 Select .如果你把所有的逻辑都放在action creator中,你最终会得到胖action对象,它们基本上会声明状态的更新.还原程序变得纯粹,愚蠢,添加这个,删除那个,更新这些函数.它们将很容易创作.但你的商业逻辑不会太多.如果你在reducer中加入更多的逻辑,你会得到很好的、很薄的动作对象,你的大部分数据逻辑都在一个地方,但是你的reducer很难编写,因为你可能需要来自其他分支的信息.你最终会得到一个或多个从州高层获取额外参数的大减缩器.

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

把更多的逻辑放在实作中与把更多的逻辑放在减缩器中是一种有效的权衡.我最近看到的一个优点是,如果你在减缩器中有更多的逻辑,这意味着如果你在进行时间旅行调试(这通常是一件好事),可以重新运行更多的东西.

我个人倾向于把逻辑同时放在两个地方.我写的动作创建者需要时间来确定是否应该发送动作,如果是,应该发送什么内容.然而,我也经常编写相应的简化程序,查看操作的内容,并执行一些复杂的状态更新作为响应.

update

自2020年起:

如果可能的话,try to put as much of the logic for calculating a new state into the appropriate reducer, rather than in the code that prepares and dispatches the action(就像一个点击处理程序).这有助于确保更多实际应用程序逻辑易于测试,能够更有效地使用时间旅行调试,并有助于避免可能导致Mutations 和错误的常见错误.

在一些有效的情况下,应首先计算部分或全部新状态(例如生成唯一ID),但应将其保持在最低限度.

Reactjs相关问答推荐

无法覆盖MUI工具栏上的左右填充,除非使用!重要

在迁移到Redux—Toolkit 2.0和Redux5.0之后,我在extraReducer和Slice方面有点挣扎,

useTranslation不会在languageChanged上重新呈现组件

如何使用皮金贴图在Reactjs中制作 map 上的点之间的线的动画?

React:关于useEffect钩子如何工作的困惑

Redux工具包-useSelector如何通过Reducer引用InitialState?

更改滑块标记的文本 colored颜色 ./Reaction/MUI 5

使用以Jest 的方式返回 Promise 的方法来模拟可构造的 API 类时出现问题

如何在不同的路由中渲染相同的页面组件(包括 getServerSideProps)

Symfony ux-react:使用react_component()时React组件不会渲染

我发送的 prop 的值不会改变.如果成功登录,导航栏中的 prop 必须为 true.我从后端得到 200 ok

React Wordpress Apache 在索引之外重新加载 -> 未找到页面

onChange in useEffect 的最佳实践

@react-three/postprocessing 没有匹配的从 three.module.js 导出以导入WebGLMultisampleRenderTarget

使用 useRef(uuid()) 的目的是什么?

为什么我在运行一些 npm react 命令时会收到这些警告?

将鼠标悬停在仅适用于该类的第一个实例的 p5.js 类上

gtag:为什么谷歌分析即使没有被授权也会收集数据

将 C# Razor 条件块转换为 React.js 代码

错误未捕获的错误:[App] 不是 组件. 的所有子组件必须是