我正在使用react和redux创建一个购物车,一切工作完美,没有任何错误,我想知道如何通过将购物车中的所有项目相加来计算总价
my cart-slice file
import { createSlice } from '@reduxjs/toolkit';
const cartSlice = createSlice({
name: 'cart',
initialState: {
items: [],
totalQuantity: 0,
},
reducers: {
addItemToCart(state, action) {
const newItem = action.payload;
const existingItem = state.items.find((item) => item.id === newItem.id);
state.totalQuantity++;
if (!existingItem) {
state.items.push({
id: newItem.id,
price: newItem.price,
quantity: 1,
totalPrice: newItem.price,
name: newItem.title,
});
} else {
existingItem.quantity++;
existingItem.totalPrice = existingItem.totalPrice + newItem.price;
}
},
removeItemFromCart(state, action) {
const id = action.payload;
const existingItem = state.items.find(item => item.id === id);
state.totalQuantity--;
if (existingItem.quantity === 1) {
state.items = state.items.filter(item => item.id !== id);
} else {
existingItem.quantity--;
existingItem.totalPrice = existingItem.totalPrice - existingItem.price;
}
},
},
});
export const cartActions = cartSlice.actions;
export default cartSlice;
cart.js文件
import { useSelector } from 'react-redux';
import Card from '../UI/Card';
import classes from './Cart.module.css';
import CartItem from './CartItem';
const Cart = (props) => {
const cartItems = useSelector((state) => state.cart.items);
return (
<Card className={classes.cart}>
<h2>Your Shopping Cart</h2>
<ul>
{cartItems.map((item) => (
<CartItem
key={item.id}
item={{
id: item.id,
title: item.name,
quantity: item.quantity,
total: item.totalPrice,
price: item.price,
}}
/>
))}
</ul>
</Card>
);
};
export default Cart;
购物车项目文件
import { useDispatch } from 'react-redux';
import classes from './CartItem.module.css';
import { cartActions } from '../../store/cart-slice';
import { useState } from 'react';
const CartItem = (props) => {
const dispatch = useDispatch();
const { title, quantity, total, price, id } = props.item;
const removeItemHandler = (e) => {
dispatch(cartActions.removeItemFromCart(id));
};
const addItemHandler = () => {
dispatch(
cartActions.addItemToCart({
id,
title,
price,
})
);
};
return (
<>
<li className={classes.item}>
<header>
<h3>{title}</h3>
<div className={classes.price}>
${total.toFixed(2)}{' '}
<span className={classes.itemprice}>(${price.toFixed(2)}/item)</span>
</div>
</header>
<div className={classes.details}>
<div className={classes.quantity}>
x <span>{quantity}</span>
</div>
<div className={classes.actions}>
<button onClick={removeItemHandler}>-</button>
<button onClick={addItemHandler}>+</button>
</div>
</div>
</li>
</>
);
};
export default CartItem;
谁能告诉我如何计算购物车的总价格?您可以在您的reducer (addItemToCart, removeItemFromCart)中执行此操作,或者添加另一个具有副作用的action的reducer。
观察你的实现,我看到你正在改变你的状态,这是一个反模式。Redux的不可变状态使用起来更安全,也更容易管理。
所以不用
state.totalQuantity++;
最好是返回一个新的状态对象
{ ...state, totalQuantity: state.totalQuantity }
我不知道redux/toolkit是否已经在内部复制了状态,但你不应该把它当作给定的。总是返回一个新状态。
现在回答你的问题(我不知道你的Item模型是什么样子的):
const totalPrice = state.items
.map(everyItem => {
return everyItem.quantity * everyItem.price;
})
.reduce((totalPrice, singleItemPrice) => totalPrice + singleItemPrice, 0);
这里的关键要点应该是https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
这将是一个记忆选择器的完美用例。由于您的状态中有一个items
数组,因此您可以创建一个选择器来将此状态减少为单个数字。例如:
const selectCart = state => state.cart
const selectTotalPrice = createSelector([selectCart], (cart) => {
return cart.items.reduce((total, item) => (item.price * quantity) + total, 0);
})