调度不改变 Redux 状态中的对象
Dispatch not changing object in Redux state
所以我正在构建一个电子商务应用程序,并且我在 redux 状态中存储了两个值来处理购物车。一个是对象数组,每个对象包含对象 ID 和数量两个键。另一个是包含产品信息的对象,其 objectID 作为键。这是我的 action/dispatch.
的代码
addToCart: (product) => {
return (dispatch, getState) => {
const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
const UPC = product.UPC;
let newQuant = 1;
let newProducts;
for(var p in productQuantity) {
if (productQuantity[p].UPC === UPC) {
newProducts = products
newQuant += productQuantity[p].quantity;
productQuantity[p] = ({UPC, quantity: newQuant});
}
}
if (!newProducts) {
console.log("not found")
productQuantity.push({UPC, quantity: 1});
newProducts = {
...products,
[UPC]: {
...product,
price: product.stores[storeKeys[storeSelected]].price,
fromStore: storeKeys[storeSelected],
}
}
}
dispatch({
type: actions.CHANGE_CART,
products: newProducts,
productQuantity
});
};
},
动作绝对运行。接下来是我的减速器。
case actions.CHANGE_CART:
console.log('This runs')
console.log(action.products);
console.log(action.productQuantity);
return {
...state,
products: action.products,
productQuantity: action.productQuantity
};
这也会执行,实际上在检查状态时,productQuantity 会在状态中更新,但 products 不会。在这一点上,我已经尝试了每一种定义配置,并且正在撕毁我的头发。将不胜感激。
我可以确认的是:
- 正在将正确的数据分派到减速器。
- reducer 执行。
- ProductQuantity 由减速器正确更新并具有正确的值。
第一个问题是您在调度操作之前改变了现有状态,mutating state is forbidden in Redux:
const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
const UPC = product.UPC;
let newQuant = 1;
let newProducts;
for(var p in productQuantity) {
if (productQuantity[p].UPC === UPC) {
newProducts = products
newQuant += productQuantity[p].quantity;
productQuantity[p] = ({UPC, quantity: newQuant});
}
}
此处对 productQuantity
的任何更改都会改变 Redux 存储中的现有数据。不要那样做。
我不太清楚products
这里是怎么回事,因为逻辑感觉有点混乱。
我的建议:
首先,开始使用our new official Redux Toolkit package。它有一个 configureStore()
功能,可以自动设置意外突变检测,如果你发生突变就会抛出错误。
其次,try to move all this modification logic into your reducer,而不是在动作创建方面进行。
第三,使用 Redux Toolkit 的 createSlice
API,它使用 Immer 库允许您在 reducer 中编写 "mutating" 逻辑并将其安全地转换为正确的不可变更新结果。
感谢 markerikson 的回复,我修改了我的 action 以不可变地处理 Redux 状态,问题已经解决。这是我更新的操作供参考。
addToCart: (product) => {
return (dispatch, getState) => {
const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
const UPC = product.UPC;
let newQuantity = 1;
for(var p in productQuantity) {
if (productQuantity[p].UPC === UPC) {
newQuantity += productQuantity[p].quantity;
}
}
dispatch({
type: actions.CHANGE_CART,
products: {
...products,
[UPC]: {
...product,
price: product.stores[storeKeys[storeSelected]].price,
fromStore: storeKeys[storeSelected],
}
},
productQuantity: productQuantity
.filter((value, index) => value.UPC !== product.UPC)
.concat([{UPC, quantity: newQuantity}])
});
};
},
所以我正在构建一个电子商务应用程序,并且我在 redux 状态中存储了两个值来处理购物车。一个是对象数组,每个对象包含对象 ID 和数量两个键。另一个是包含产品信息的对象,其 objectID 作为键。这是我的 action/dispatch.
的代码addToCart: (product) => {
return (dispatch, getState) => {
const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
const UPC = product.UPC;
let newQuant = 1;
let newProducts;
for(var p in productQuantity) {
if (productQuantity[p].UPC === UPC) {
newProducts = products
newQuant += productQuantity[p].quantity;
productQuantity[p] = ({UPC, quantity: newQuant});
}
}
if (!newProducts) {
console.log("not found")
productQuantity.push({UPC, quantity: 1});
newProducts = {
...products,
[UPC]: {
...product,
price: product.stores[storeKeys[storeSelected]].price,
fromStore: storeKeys[storeSelected],
}
}
}
dispatch({
type: actions.CHANGE_CART,
products: newProducts,
productQuantity
});
};
},
动作绝对运行。接下来是我的减速器。
case actions.CHANGE_CART:
console.log('This runs')
console.log(action.products);
console.log(action.productQuantity);
return {
...state,
products: action.products,
productQuantity: action.productQuantity
};
这也会执行,实际上在检查状态时,productQuantity 会在状态中更新,但 products 不会。在这一点上,我已经尝试了每一种定义配置,并且正在撕毁我的头发。将不胜感激。
我可以确认的是:
- 正在将正确的数据分派到减速器。
- reducer 执行。
- ProductQuantity 由减速器正确更新并具有正确的值。
第一个问题是您在调度操作之前改变了现有状态,mutating state is forbidden in Redux:
const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
const UPC = product.UPC;
let newQuant = 1;
let newProducts;
for(var p in productQuantity) {
if (productQuantity[p].UPC === UPC) {
newProducts = products
newQuant += productQuantity[p].quantity;
productQuantity[p] = ({UPC, quantity: newQuant});
}
}
此处对 productQuantity
的任何更改都会改变 Redux 存储中的现有数据。不要那样做。
我不太清楚products
这里是怎么回事,因为逻辑感觉有点混乱。
我的建议:
首先,开始使用our new official Redux Toolkit package。它有一个 configureStore()
功能,可以自动设置意外突变检测,如果你发生突变就会抛出错误。
其次,try to move all this modification logic into your reducer,而不是在动作创建方面进行。
第三,使用 Redux Toolkit 的 createSlice
API,它使用 Immer 库允许您在 reducer 中编写 "mutating" 逻辑并将其安全地转换为正确的不可变更新结果。
感谢 markerikson 的回复,我修改了我的 action 以不可变地处理 Redux 状态,问题已经解决。这是我更新的操作供参考。
addToCart: (product) => {
return (dispatch, getState) => {
const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
const UPC = product.UPC;
let newQuantity = 1;
for(var p in productQuantity) {
if (productQuantity[p].UPC === UPC) {
newQuantity += productQuantity[p].quantity;
}
}
dispatch({
type: actions.CHANGE_CART,
products: {
...products,
[UPC]: {
...product,
price: product.stores[storeKeys[storeSelected]].price,
fromStore: storeKeys[storeSelected],
}
},
productQuantity: productQuantity
.filter((value, index) => value.UPC !== product.UPC)
.concat([{UPC, quantity: newQuantity}])
});
};
},