javascript - 事件和 Action 是否有 1 :1 relationship in Redux?

标签 javascript events action redux

事件(DOM 事件或系统事件)是否与操作具有 1:1 的关系?即一次点击事件是否应该只触发一个 Action ?

例如,假设我们有一个页面显示一个 10 行 2 列的表格。每行都有一个 Product 字段和一个 Amount 字段。 Amount 字段有一个范围为 [0, 10] 的范围输入。用户可以单独设置每个产品的金额。

用户还可以通过使用 2 个按钮获得 2 个选项。

  • 按下第二个按钮将禁用表格中除第一个产品以外的所有产品(实际上将其数量设置为 0,用户无法再与它们交互以设置其数量)。我们称此为选项 B
  • 按下第一个按钮会启用第一个按钮之后的所有产品(默认情况下将每个产品的数量设置为 1),用户可以再次与它们互动,以单独设置它们的数量。我们称此为选项 A

Option A selected:

    | PRODUCT          | AMOUNT    |
    |------------------|-----------|
    | Product A        |   - 4 +   |
    | Product B        |   - 0 +   |
    | Product C        |   - 4 +   |
    ````````````````````````````````

 _________
| Option A|  OPTION B
 `````````

Option B selected:

    | PRODUCT          | AMOUNT    |
    |------------------|-----------|
    | Product A        |   - 4 +   |
    | Product B        |  Disabled | (Amount == 0)
    | Product C        |  Disabled | (Amount == 0)
    ````````````````````````````````

          _________
OPTION A | OPTION B|
          `````````

Option A selected again:

    | PRODUCT          | AMOUNT    |
    |------------------|-----------|
    | Product A        |   - 4 +   |
    | Product B        |   - 1 +   |
    | Product C        |   - 1 +   |
    ````````````````````````````````

 _________
| Option A|  OPTION B
 `````````


The state of this 'app' is described by this simple object

state = {
    option : <String>,
    products : [
        {
            name : <String>,
            amount : <Integer>
        }, ...
    ]
}

我们还有这 4 个简单的 Action 创建器:

function setOption(option) {
    return { type : 'SET_OPTION', option : option};
}

function incAmount(productName) {
    return {
        type : 'INCREMENT_AMOUNT',
        product : productName
    }
} 

function decAmount(productName) {
    return {
        type : 'DECREMENT_AMOUNT',
        product : productName
    }
}

function setAmount(productName, amount) {
    return {
        type : 'SET_AMOUNT',
        payload : { product : productName, amount : amount }
    }
}

为了简单起见,我们只有一个reducer。

在此示例中,选择选项 B 会对状态产生以下影响:

  • 选项更改为B
  • 将第一个之后的每个产品的数量设置为0

选择 选项 A 应该分别对状态产生以下影响:

  • 选项更改为A
  • 将第一个之后的每个产品的数量设置为1

增加产品 A 的数量应该对状态产生以下影响:

  • 将产品 A 的数量增加 1

实现这些更改的正确方法是什么?

a)option 按钮的 onClick 处理程序执行以下操作:

  • 触发 store.dispatch(setOption(option))
  • 对于第一个之后的每个产品触发一个 store.dispatch(setAmount(productName, amount))(amount = 1 选项 A,0 选项 B)

b)option 按钮的 onClick 处理程序执行以下操作:

  • 触发 store.dispatch(setOption(option))

    并让 reducer 将第一个产品之后的每个产品的 optionamount 更改为指定数量(amount =选项 A 为 1,选项 B 为 0)

如果我们使用 a) reducer 的 switch (action) {} 语句中的每个 case 只处理状态的一个方面,但我们必须从一个click事件

触发多个 Action

如果我们使用 b),我们只会从 click 事件中触发一个 Action ,但是在 reducer 中 SET_OPTION 的情况不仅会改变选项,还有产品的数量

最佳答案

这个问题没有统一的答案,所以我们必须根据具体情况进行评估。

使用 Redux 时,您应该努力在保持 reducer 简单和保持操作日志有意义之间保持平衡。最好是当您可以阅读操作日志并且了解事情发生的原因时。这就是 Redux 带来的“可预测性”方面。

当您发送单个操作时,状态的不同部分响应发生变化,很容易告诉您为什么它们稍后会发生变化。如果您调试一个问题,您不会被大量的操作弄得不知所措,而且每个突变都可以追溯到用户所做的事情。

相比之下,当您分派(dispatch)多个操作以响应单个用户交互时,就很难告诉为什么分派(dispatch)它们。它们使操作日志困惑,如果它们的调度方式有误,日志将无法揭示根本原因。

一个好的经验法则是你永远不想在循环中dispatch。这是非常低效的,并且如上所述,掩盖了发生变化的原因的真实性质。在您的特定示例中,我建议触发单个操作。

然而,这并不意味着触发单个 Action 是总是的方式。像所有事情一样,这是一种权衡。在某些情况下,触发多个操作以响应单个用户交互会更方便。

例如,如果您的应用允许用户标记产品,则将 CREATE_TAGADD_TAG_TO_PRODUCT 操作分开会更方便,因为在这种情况下它们会同时发生,它们也可能单独发生,并且编写将它们作为不同操作处理的 reducer 会更容易。只要您不滥用此模式并且不在循环中执行此类操作,您应该没问题。

让操作日志尽可能接近用户交互的历史记录。但是,如果 reducers 难以实现,请考虑将一些操作分成几个,如果 UI 更新可以被认为是恰好在一起的两个独立操作。不要陷入任何一个极端。更喜欢 reducer 的清晰度而不是完美的日志,但也更喜欢不在循环中调度以降低 reducer 的清晰度。

关于javascript - 事件和 Action 是否有 1 :1 relationship in Redux?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35406707/

相关文章:

Android:如何自动接听电话?

javascript - 避免 jQuery Mobile 使用 _=TIMESTAMP 查询字符串参数强制重新加载脚本/CSS

javascript - 从 data.task 迁移到处理拒绝的 folktale

javascript - Web3 错误 : Transaction has been reverted by the EVM:

events - Magento Cookie 和数据库在页面加载时工作

reactjs - Typescript 与复杂的 redux 操作和化简器集成

android tv leanback 应用列表

javascript - Dailymotion 自动播放无法在移动设备上运行

Java在不相关的类之间创建事件

javascript - JS。将事件属性类型分配给变量