gpt4 book ai didi

redux - 更改数组项的最佳方法是什么?

转载 作者:行者123 更新时间:2023-12-04 13:18:37 25 4
gpt4 key购买 nike

在Redux中更改存储数组元素的最佳方法是什么?我有以下3种可行的解决方案。我认为前两种解决方案正在改变状态。是真的吗
如果您有更好的解决方案,我将不胜感激。

在此示例中,我有一个订单 list ,并且我想增加 list 中一个订单的数量。我将此订单索引作为orderIndex传递给了操作。

第一种方式:

let order = state[action.orderIndex];
order.quantity++;
return Object.assign([],order);

第二种方式:
let order= Object.assign([],state);
order[action.orderIndex].quantity++;
return Object.assign([],order);

第三种方式:
return Object.assign([],state.map(
(order,index) => (index==action.orderIndex) ? {...order,quantity:order.quantity+1} : order)
);

我有另一个解决方案,但它返回一个对象,并且我不知道如何在此解决方案中返回数组。 :
            return {...state,[action.orderIndex]:{...state[action.orderIndex],quantity:state[action.orderIndex].quantity+1}};

最佳答案

第一个修改原始顺序,这是一个突变。这违反了Redux存储的不变性。

第二个复制数组,但是数组内的对象仍然是原始顺序。他们只是引用与原始数组相同的实例。因此,当您在下一行修改其中之一时,您正在改变Redux状态。

第三种方法很有趣,因为即使您不改变状态,也可以简化它。

return state.map(order => (index==action.orderIndex) ? {...order, quantity: order.quantity+1} : order);

由于 map函数已经返回了一个新数组,因此无需调用 Object.assign

第三种版本有效,因为您引用的是所有未修改的订单,并且仅针对要更改的一个项目创建新订单。由于不允许进行突变,因此您需要创建一个新对象。

现在,ES6语法可能会令人困惑。您可以使它完全在没有ES6的情况下工作(除了 Object.assign,但可以使用下划线的 extend替换它。重要的是,没有使用新语法)。
// copy the list so we can modify the copy without mutating the original
// it is important to realize that even though the list is brand new
// the items inside are still the original orders
var newOrders = state.slice();
// grab the old order we'd like to modify
// note that we could have grabbed it from state as well
// they are one and the same object
var oldOrder = newOrders[action.orderIndex];
// this takes a new object and copies all properties of oldOrder into it
// it then copies all properties of the final object into it
// the final object has only our new property
// we could have multiple properties there if we needed
var newOrder = Object.assign({}, oldOrder, { quantity: oldOrder.quantity + 1 });
// now we just replace the old order with the new one
// remember it's okay to modify the list since we copied it first
newOrders[action.orderIndex] = newOrder;
return newOrders;

或者,您可以直接修改副本,如下所示:
var newOrders = state.slice();
var oldOrder = newOrders[action.orderIndex];
// make a shallow copy
var newOrder = Object.assign({}, oldOrder);
// we can now modify immediate properties of the copy
newOrder.quantity++;
newOrders[action.orderIndex] = newOrder;
return newOrders;

两种处理方式之间的区别在于,使用 map的版本(以及更多的ES6重型版本)是单个表达式。这使其更具功能性。您无需指定获取结果的步骤,而是可以指定结果的外观。它是声明式还是命令式。

声明性版本有时会更清晰。再一次,通常不是。它通常更短,但看起来却很陌生。如果您来自功能世界,那么它的外观和感觉是完全正常的。外星人从不认为自己是外星人。

我建议易于理解比短代码更重要。请注意,它不可能更快。例如, map版本会为每个订单调用您的函数。

如果您有几百万个订单(我们都希望得到),我们最终将检查每个订单,以查找是否要修改该订单。

但是,当使用命令式版本时,您需要复制数组,该操作在此期间我们不检查任何订单。它比 map版本快很多,而且快得多。

那么,为什么我们看到人们使用 map?好吧,如果您只有几个订单,性能就不成问题了,对于那里的功能纯粹主义者来说,它看起来还不错。

ES6的做事方式也有Mark的回答。它通过在要替换的项目之前复制零件,添加新的项目,然后在要替换的项目之后添加零件来创建新阵列。很快(在我看来)这也很丑陋。

当然,如果您考虑一下,它会做什么。它替换了我们需要更改的一项。但是,它看起来不像是替代品。实际上,索引中唯一未提及的项目就是我们要替换的项目。

我想说的是,除非您试图证明整个应用程序只是一个单一的表达式,否则编写命令式代码是完全可以的。如果更容易理解或编写,则没有理由不这样做。

关于redux - 更改数组项的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40603134/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com