在动作与属性中传递对象

Passing objects in actions vs attributes

在我在 redux repo 中看到的示例中,操作对象似乎总是包含我们所处状态的属性 creating/editing 而不是直接传入对象。例如

/* In the action creator */
export function addTodo(text) {
  return { type: types.ADD_TODO, text }
}

/* In the reducer */
....
case ADD_TODO:
  return [
    {
      id: state.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1,
      completed: false,
      text: action.text
    }, 
    ...state
  ]

用这种方式代替直接在操作中传递 'todo' 对象并在缩减器中添加任何缺失的元素有什么特别的优势吗?

我正在开发一个应用程序,其中传入的对象有很多属性,我发现我必须在每个 reducer 函数中重复从操作中提取这些属性。在前面的示例中,将 action.todo 设置为相关对象并让 reducer 仅添加缺少的任何属性(例如 id)不是更容易吗?

这是我没能理解的某种convention/pattern吗?

老实说,我建议这种设计决策 "up to you," 就像您正在查看的代码的设计者所做的那样。几乎在所有情况下,一种方法与任何其他方法相比没有 绝对 优势。

如果您发现,在您的情况下,您是 "repeating yourself,",尤其是如果您注意到 "extraneous" 位在 "every" reducer 函数中似乎是 showing-up,那么我建议你应该跟随你的直觉。您在用作模型的代码中看到的策略很可能适合您的案例,而您应该感到完全有权做出 工程 决定。

换句话说:恕我直言,从工程的角度来看,我当然不喜欢看到任何东西 "repeated in every case," 除非它真的 属于 属于 "every case," 因为否则它 耦合 许多 (否则 "unrelated") 例一起!

思考: "what if such-and-such change needed to be made in the future? Would the change be "适当隔离,”或者它会"ripple"跨越整个source-code宇宙像Jell-O 和 "for no good reason?" 来自 软件工程 point-of-view 的地狱碗 "suck ... for no good reason." 因此,谨慎的做法是避免它。

总的来说,我认为您的操作应该尽可能简单,只传达他们需要的最少信息量。但是您当然可以将操作的结构更改为更便于处理的格式。一种常见的模式是使用 payload 键指向所有数据。例如

    /* In the action creator */
    export function addTodo(text, date, priority) {
      return {
        type: types.ADD_TODO,
        payload: {
          text,
          date,
          priority
        }
      };
    }

    /* In the reducer */
    case ADD_TODO:
      return [
        Object.assign({}, action.payload, {
          id: newId()
        }, 
        ...state
      ];

您的有效负载构成了待办事项对象的基础。您只提取了一个属性,而不是提取多个属性。

这是一个旧的 post 但仍然值得额外回答。我也来自 OO 编程世界,我也偶然发现了这个:

通常建议您将 json 传递给 redux 操作,而不是传递给它的对象,因为它允许拥有更舒适的调试和测试功能。对于两者,您需要序列化您的“数据”,如果此数据是 object/instance 等,则无法完全序列化。这与传递的对象的单纯属性或配置相反。 它对如何完成事情有不同的看法,而且好处非常多。

注意措辞谨慎——我不能说你不应该传递一个实例,也不能说最好不要传递一个实例。但这是今天的常识,首选方式。

这里再多说几句: https://redux.js.org/faq/design-decisions#why-doesnt-redux-support-using-classes-for-actions-and-reducers