当我需要深入研究数据结构时,我经常发现自己遵循这种模式,特别是在我的Redux reducer中:
state.items = state.items.map((item) => {
item.subItems = item.subItems.map((subItem) => {
subItem.bottomItems = subItem.bottomItems.map((bottomItem) => {
// do something with bottomItem...
bottomItem.foo = 'bar';
return bottomItem;
});
return subItem;
});
return item;
});
这似乎是很多样板,可以达到bottomItems
级别。
ES6或ES7是否提供了一些语法糖来缓解这种模式?
答案 0 :(得分:2)
我应该首先提到的是,你所拥有的代码会修改原始状态。要维护redux的state immutability principle,您只想返回新对象而不是修改现有对象。
就简单的语法而言,如果使用arrow functions和object spread,这种模式并不是那么糟糕:
return {
items: state.items.map(item => ({
...item,
subItems: item.subItems.map(subItem => ({
...subItem,
bottomItems: subItem.bottomItems.map(bottomItem => ({
...bottomItem,
foo: 'bar' // update foo to 'bar' for every bottomItem in every subItem in every item
})
})
})
}
请注意,对象传播还不是该语言的一部分,它目前是第3阶段提案,可能会成为下一个ECMAScript版本的一部分。因此,您必须使用像Babel这样的东西来在当今的浏览器中工作。
如果您不希望这样做,并且想要今天可以使用的功能,则可以使用Object.assign代替:
return {
items: state.items.map(item => Object.assign({}, item, {
subItems: item.subItems.map(subItem => Object.assign({}, subItem, {
bottomItems: subItem.bottomItems.map(bottomItem => Object.assign({}, bottomItem, {
foo: 'bar' // update foo to 'bar' for every bottomItem in every subItem in every item
})
})
})
}
由于您似乎想要更清晰,更易读的语法,我建议选项1:)
答案 1 :(得分:1)
是的,嵌套的不可变更新可能很麻烦(正如我在Redux文档的Structuring Reducers - Immutable Update Patterns部分中提到的那样)。
您可能希望使用其中一个不可变更新实用程序库。这些库提供了各种语法和抽象,用于执行更简单的嵌套不可变更新。一些使用字符串键路径,另一些使用嵌套对象定义。典型示例可能是someLib.set(["items", "subItems", "bottomItems", 0, "someField"], someValue)
。
请参阅Immutable Data#Immutable Update Utilities的Redux addons catalog部分,了解可用的库列表。