#reactjs #state
#reactjs #состояние
Вопрос:
Использую React useReducer и пытаюсь выполнить обновление состояния и повторно отобразить react по мере внесения изменений.
JSX вызывает редуктор:
<button onClick={() => dispatch({ type: "DECREMENT", item })} > </button>
и useReducer:
const reducer = (state, action) => {
const { item, type } = action;
switch (type) {
case "INCREMENT": {
const newCart = state;
const u = { ...item, quantity: item.quantity 1 };
const index = newCart.findIndex(eachitem => item.id === eachitem.id);
newCart.splice(index, 1, u);
console.log("INCREMENT", newCart);
return newCart;
}
case "DECREMENT": {
const newCart = state;
const u = { ...item, quantity: item.quantity - 1 };
const index = newCart.findIndex(eachitem => item.id === eachitem.id);
newCart.splice(index, 1, u);
console.log("DECREMENT", newCart);
return newCart;
}
case "REMOVE": {
return state.filter(eachitem => item.id !== eachitem.id);
}
default: {
return state;
}
}
};
Полный код можно найти ниже.
Ответ №1:
Ваш редуктор не может обнаружить изменение состояния, поскольку вы возвращаете тот же объект. Изменение обнаружено путем сравнения предыдущего значения состояния и нового, путем ===
сравнения или Object.is()
comparison, что в принципе одно и то же (не уверен, какое именно, можете попробовать найти в React docs).
Поэтому вместо:
const newCart = state;
Вам нужно сделать:
// shallowly copy the state so now Object.is(newState, prevState) returns false
const newCart = [...state];
...
return newCart
Комментарии:
1. Это выглядит лучше, чем возврат нового объекта 🙂👍
2. Имеет смысл. Я создал NewCart, чтобы избежать мутирования, но поскольку это объект, он указывает на тот же объект (и я его мутировал). Распространяя состояние на новый объект, оно создает неглубокую копию и фактически ссылается на новый объект. Спасибо
Ответ №2:
Вы устанавливаете newCart
в качестве состояния, которое указывает на то же самое. Либо вы клонируете состояние, либо возвращаете новый экземпляр объекта.
switch (type) {
case "INCREMENT": {
const newCart = state;
const u = { ...item, quantity: item.quantity 1 };
const index = newCart.findIndex(eachitem => item.id === eachitem.id);
newCart.splice(index, 1, u);
console.log("INCREMENT", newCart);
return [...newCart];
}
case "DECREMENT": {
const newCart = state;
const u = { ...item, quantity: item.quantity - 1 };
const index = newCart.findIndex(eachitem => item.id === eachitem.id);
newCart.splice(index, 1, u);
console.log("DECREMENT", newCart);
return [...newCart];
}
case "REMOVE": {
return state.filter(eachitem => item.id !== eachitem.id);
}
default: {
return state;
}
}
};