gpt4 book ai didi

javascript - 发生Redux状态更改时,组件不会更新

转载 作者:行者123 更新时间:2023-12-01 00:16:18 25 4
gpt4 key购买 nike

case 'ADD_TO_CART': {
let item = action.payload;
let newState = addToCart(state, item);
return newState;
}
const increaseItem = (array = [], dish) => {
array.filter((item) => {
if (item.id === dish.id) {
item.quantity++;
}
});
return array;
}

case 'INCREASE_ITEM': {
let item = action.payload;
console.log('run in increase')
let newState = increaseItem(state, item);
return newState;
}


这是代码。
问题是当属性数量增加时,redux认为状态没有变化,因此mapStateToProps无法运行。
请问有什么解决办法吗?

最佳答案

数组filter返回一个新数组,它不会更新原始数组。直接返回或保存到变量以进行更改

const increaseItem = (array = [], dish) => {
return array.filter(//your code here);
//return array;
}

// OR

const increaseItem = (array = [], dish) => {
const newArray = array.filter(//your code here);
return newArray;
}


但是,这并没有按照您的想法进行。您应该改用 map

const increaseItem = (array = [], dish) => {
return array.map((item) => {
if (item.id === dish.id) {
item.quantity++;
}
return item; // Add this
});
}


filter仅在回调函数返回true时才从数组返回值。您的函数没有检查是否应该过滤,而是在尝试修改值(并且是)。

map将为数组的每个索引返回回调的值。因此,如上所示,如果在最后返回每个项目,则给定的回调应该执行预期的操作。

问题的最后一部分是确保您不改变状态。这很可能是问题的根源。

const increaseItem = (array = [], dish) => {
return array.map((item) => {
let item = {...item}; // Add this
if (item.id === dish.id) {
item.quantity++;
}
return item;
});
}


使用 mapfilter,您可以创建一个新的状态数组。但是,当执行 item.quantity++;时,您将同时更改原始状态和新状态的嵌套对象,因为嵌套对象仍使用相同的引用。在映射时创建新对象可确保不仅主状态数组是新的,而且还确保任何嵌套对象也是如此(此特定示例仅保护1个深度)。

说明

它的长度比答案要长,但是我想弄清楚。

您遇到的问题是一个非常普遍的问题,与JavaScript处理非原始数据类型的方式有关。当您创建数组或对象并将其分配给变量时,该变量实际上并不包含该对象,它包含对该对象的引用或指针。对象本身实际上存储在内存中的其他位置。

为了清楚起见,让我们仅用由 <>包围的数字来表示引用。
让我们创建一个对象:

let obj1 = {a: 'b'};


obj1保存对我们创建的新对象的引用,可以说引用为<1>。现在让我们复制对象。



let obj1 = {a: 'b'};
let obj2 = obj1;

console.log(obj1);
console.log(obj2);





由于变量包含引用,因此实际分配 obj2的是与<1>相同的引用。

obj1 
// reference: <1>
// value: {a: 'b'}

obj2
// reference: <1>
// value: {a: 'b'}


之所以会出现误解,是因为人们认为 obj2现在是它自己的原始副本。但是如您所见,它们引用内存中的同一对象。结果是,现在执行类似 obj2.a = 'c'的操作会导致 obj1.a也等于'c'。

运行下面的代码片段,自己看看:



let obj1 = {a: 'b'};
let obj2 = obj1;

obj2.a = 'c';

console.log(obj1);
console.log(obj2);





我们如何避免制作误导性的副本?

最简单的方法是创建一个全新的对象,并通过 destructuring用旧对象的值填充它。



let obj1 = {a: 'b'};
let obj2 = {...obj1};

// obj1
// reference: <1>
// value: {a: 'b'}

// obj2
// reference: <2>
// value: {a: 'b'}

obj2.a = 'c';

console.log(obj1);
console.log(obj2);





现在您可以看到我们已经复制了一个对象,但是每个对象都在内存中引用了自己的对象。这几乎总是我们想要的行为。

当我们引入嵌套时,事情变得更加混乱。但是,如果您了解基本概念,它应该更有意义。

let obj1 = {
foo: 'bar',
nested: {a: 'b'}
};

// obj1
// reference: <1>
// value: {foo: 'bar', nested: <2>}

// nested
// reference: <2>
// value: {a: 'b'}


嵌套对象也获得自己的引用。因此,当我们分解以创建新对象时,这就是我们正在做的事情。

let obj2 = {...obj1};

obj1
// reference: <1>
// value: {foo: 'bar', nested: <2>}

nested
// reference: <2>
// value: {a: 'b'}

obj2
// reference: <3>
// value: {foo: 'bar', nested: <2>}


obj2引用了内存中的新位置,但是嵌套对象仍然具有与以前相同的引用!

因此,即使我们在顶部创建了一个新对象,如果我们修改嵌套属性,我们的行为也会与以前类似。这称为“浅拷贝”。试试看:



let obj1 = {
foo: 'bar',
nested: {a: 'b'}
};

let obj2 = {...obj1};

obj2.nested.a = 'c';

console.log(obj1);
console.log(obj2);





解决方案:也使所有嵌套值的新对象。

let obj2 = {...obj1, nested: {...obj1.nested}};


现在,我们已经成功创建了嵌套对象的完全独立的副本。

obj1 
// reference: <1>
// value: {foo: 'bar', nested: <2>}

nested
// reference: <2>
// value: {a: 'b'}

obj2
// reference: <3>
// value: {foo: 'bar', nested: <4>}

nested
// reference: <4>
// value: {a: 'b'}


您可以放心地编辑 obj2及其嵌套值,以确保 obj1及其嵌套值将保持不变。



let obj1 = {foo: 'bar', nested: {a: 'b'}};
let obj2 = {...obj1, nested: {...obj1.nested}};

obj2.nested.a = 'c';

console.log(obj1);
console.log(obj2);

关于javascript - 发生Redux状态更改时,组件不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59738516/

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