【问题标题】:ReactJs/Flux: How to handle editing process of store objects?ReactJs/Flux:如何处理存储对象的编辑过程?
【发布时间】:2015-12-06 18:14:57
【问题描述】:

处理从商店检索到的编辑对象的最佳方法是什么?

例如假设你有一个 ProductStore 你有一个 EditProductComponent。如果您将正在编辑的状态产品设置如下:

this.state.product = ProductStore.getProductById(1); 

问题是,当用户在进行了一些更改后取消编辑时,他们会保留在 store 对象上,因为它是直接分配给状态的。例如。用户修改产品名称:

this.state.product.name = value; //new value is assigned to the store object as well

我怎样才能使它具有性能并使其商店产品保持只读状态?

我正在考虑使用 Object.assign 从商店返回一个克隆,以确保原始对象保持不变。但这会为每个 get 请求返回新对象,这似乎根本没有性能。

【问题讨论】:

  • 你应该看看 Immutable.js,我认为它可能非常适合你的需求
  • 感谢您的反馈。一定会检查出来的。但是,它是否是针对特定用例的推荐解决方案,遵循通量模式?
  • 不要直接设置状态变量,而是使用 setState。当用户决定保存更改时,使用操作来更新商店的值。

标签: reactjs reactjs-flux


【解决方案1】:

每次实际开始影响性能时,您必须执行 大量 请求才能创建克隆。

复制一个对象并不是一个特别昂贵的操作,当你的引用超出范围时垃圾收集器会清理,所以你可能也不需要担心内存。

与知道商店中的数据不能从应用程序的其他地方随机变异所带来的可预测性优势相比,这些权衡是非常小的。

getProductById: function(id) {
  var product = this.products[id];

  return Object.assign({}, product);
}

但是,您可以更进一步,让它们不可变。

getProductById: function(id) {
  var product = this.products[id];

  return Object.freeze(product);
}

现在无法再对产品进行变异。如果您的应用程序的另一部分想要对其进行编辑,则必须改为创建一个应用了适当更改的新副本。

// the immutable product that came from the store
const product = { ... };

// with ES6
const editedProduct = Object.assign({ editedProp: newValue }, product);
// or with ES7
const editedProduct = { editedProp: newValue, ...product };

您还必须记住,只要您想修改对象,就更新商店。

ProductStore.edit(editedProduct.id, editedProduct);

这使您可以在整个应用程序中强制执行可预测性。

另一种选择是使用实现不可变数据结构的库,例如Immutable.js

它带有一个immutable map type,可以像对象一样使用,但是当您尝试更改或创建属性时,它不会改变它,而是返回一个不可变映射。

var product = Immutable.Map({ name: 'product_name' });
var editedProduct = product.set('name', 'new_name');

// now tell the store that you've edited it
// ...

这里最大的好处是 Immutable.js 使用一种称为结构共享的技术来确保在内部尽可能多的对象在两个版本之间共享,使它们几乎与常规可变数据结构一样高效。

库创建者的a great video 很好地涵盖了这些概念。值得一看。

【讨论】:

  • 感谢完整的解释!
  • “现在不能再对产品进行变异了”。有点。Object.freezeObject.assign 都是浅层操作,因此实际上并不能解决问题。例如 o = {a: {b: 1, c: 1}}; Object.freeze(o); o.a.b = 2; Object.assign({}, o).a.c = 2 和现在o == {a: {b: 2, c: 2}}。要么你需要勤奋并在任何地方深度冻结/复制,要么只使用完全不可变的数据结构。
  • Andrew 提出了一个很好的观点,如果您的产品对象是复合的(它们由其他对象组成),那么您将需要递归解决方案。但是,如果您的对象只是键和值的一级深度映射,这不是问题。
  • 我同意,我决定采用 immutable.js 的不可变路线。不过感谢您的提醒!
猜你喜欢
  • 2015-05-11
  • 2012-04-09
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 2013-01-05
相关资源
最近更新 更多