Redux 操作不会更新 react-redux 中的 redux 状态



每当我单击添加到购物车按钮时,都会触发操作,但 redux 状态不会更新(初始状态没有改变,但操作被触发)。

const CartScreen = () => {
const { id } = useParams();
const { search } = useLocation();
const [searchParms] = useSearchParams();

const productId = id;
const qty = search ? Number(search.split("=")[1]) : 1;

const dispatch = useDispatch()
useEffect(() => {
if (productId){
dispatch(addToCart(productId, qty))
}

}, [dispatch, productId, qty])

return (
<div>
<h1>Add to CART</h1>
</div>
);
};

export default CartScreen

购物车操作

export const addToCart = (id, qty) => async (dispatch, getState) =>{
const {data} = await axios.get(`http://127.0.0.1:8000/api/products/${id}`)
dispatch({
type: CART_ADD_ITEM,
payload:{
product:data._id,
name:data.name,
image:data.image,
countInStock:data.countInStock,
qty
}
})
localStorage.setItem('cartItems', JSON.stringify(getState().cart.cartItems))
}

推车减速机

export const cartReducer = (state = { cartItems: []}, action) =>{
switch(action.type){
case CART_ADD_ITEM:
const item = action.payload
const existItem = state.cartItems.findIndex(x => x.product === item.product)
if (existItem){
return{
...state,
cartItems: state.cartItems.map(x => 
x.product === existItem.product ? item : x)
}
} else{
return{
...state,
cartItems:[...state.cartItems, item]
}
}
default:
return state
}
}

Redux 存储

const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
})
const initialState = {
cart:{cartItems:cartItemsFromStorage}
};
const middleware = [thunk];
const store = createStore(
reducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);

从 redux 开发工具中,我可以看到我触发的操作。该项目正在进入购物车缩减器,因为当我控制台时.logitem从 cartReducerconst item=action.payload,我在浏览器控制台中获取特定项目,但 cartItem redux 状态仍为初始值,它没有更新

Array.prototype.find()- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

Array.prototype.findIndex()- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

使用 Array.prototype.findIndex() 基本上会查找并返回第一个找到的项目的索引,如果没有找到,则-1。而 Array.prototype.find() 返回数组中与提供的条件匹配的第一个元素。

export const cartReducer = (state = { cartItems: [] }, action) => {
switch(action.type){
case CART_ADD_ITEM:
const item = action.payload;
// use Array.prototype.find() instead
// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
const existItem = state.cartItems.find(x => x.product === item.product);
if (existItem){
return{
...state,
cartItems: state.cartItems.map(x =>
x.product === existItem.product ? item : x)
};
} else{
return{
...state,
cartItems: [...state.cartItems, item]
};
}
default:
return state;
}
};

问题是您正在搜索现有产品并返回找到的索引 (array.findIndex),然后将索引值用作布尔条件 (if (existItem) {...})。

这不会像您期望的那样工作,因为所有非零数字都是真实的,而0是假的。这意味着,如果没有购物车物料产品匹配该-1,则返回该商品,逻辑会将其视为现有商品。稍后通过array.map更新购物车时,情况会更加复杂...如果existItem-1这意味着没有匹配的产品,新state.cartItems将是一个新数组,但它不包含新的item对象。换句话说,它只是先前状态的副本。

cartItems最初以空数组开始,因此existItem首次将商品添加到购物车时将始终返回-1

当产品确实存在于cartItems数组中并且它是第 0 个元素时,会发生额外的意外错误。existItem将等于0,因此是假的,item将作为副本添加到数组cartItems

关于使用array.findIndexarray.find,@Chigbogu是正确的,尽管如果您只是检查购物车项目数组是否有该项目,我建议您使用array.some。这表示您正在显式使用布尔值。将existItem重命名为hasItem或类似名称,以便名称也指示布尔值(这是按照惯例)。

export const cartReducer = (state = { cartItems: []}, action) =>{
switch(action.type) {
case CART_ADD_ITEM: {
const newItem = action.payload;
const hasItem = state.cartItems.some(item => item.product === newItem.product);
if (hasItem) {
return {
...state,
cartItems: state.cartItems.map(item => 
item.product === newItem.product ? newItem : item
)
}
} else {
return {
...state,
cartItems: [...state.cartItems, newItem]
}
}
}
default:
return state;
}
};

相关内容

  • 没有找到相关文章

最新更新