Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
345 views
in Technique[技术] by (71.8m points)

javascript - Component won't update when a redux state change occurs

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;
}

Here is the code. Problem is when the properties quantity increase, redux think the state has no change so mapStateToProps not run. Is there any solution for this please?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Array filter returns a new array, it does not update the original. Return directly or save to a variable to make changes

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;
}

However, this is not doing what you think it is. You should use map instead

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

filter will only return values from the array if the callback function returns true. Your function isn't checking if it should filter, its trying to modify values (and is).

map will return the value of the callback for each index of the array. So your given callback should do what you expect if you return each item at the end as shown above.

The last piece of the problem is to ensure you don't mutate state. This is most likely the root your problem.

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

With map and filter, you are creating a new state array. But, when doing item.quantity++;, you are mutating a nested object in both the original state and new state, as the nested objects are still using the same references. Creating a new object while mapping ensures that not only the main state array is new, but also any nested objects as well (this specific example only protects 1 deep).

Explanation

Its longer than the answer, but I wanted to make it clear.

The problem you're having is a very common one, and has to do with how JavaScript handles non-primitive data types. When you create an array or object and assign it to a variable, the variable doesn't actually contain the object, it contains a reference or a pointer to the object. The object itself is actually stored somewhere else in memory.

For clarity, lets just denote references by numbers surrounded by <>. Lets create an object:

let obj1 = {a: 'b'};

obj1 holds the reference to the new object we created, lets say the reference is <1>. Now lets make a copy of the object.

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

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...