我在React-Redux购物车上做了一个项目。我目前正在尝试构建功能,以允许用户更新添加到购物车的商品数量。我已经能够从购物车中删除"上班。我一直在寻找不同的方法,但似乎所有的购物车教程都停留在"添加到购物车"!所以我一直试图通过它来解决这个问题,但在网上找到了很少的例子。有人能指出我正确的方向吗?
这是最初在Github上发布的购物车教程: https://github.com/reactjs/redux/tree/master/examples/shopping-cart
这是我一直想弄清楚的事情:
ProductItem.js
const ProductItem = ({product, onAddToCartClicked, onRemoveFromCartClicked, onIncreaseQuanityClicked, onDecreaseQuantityClicked }) => (
<div style={{ marginBottom: 20, marginLeft: 20}}>
<Card>
<CardBody>
<Product
title={product.title}
price={product.price}
inventory={product.inventory} />
<Button color="primary"
onClick={onAddToCartClicked}
disabled={product.inventory > 0 ? '' : 'disabled'}>
{product.inventory > 0 ? 'Add to cart' : 'Sold Out'}
</Button>
<Button color="success"
onClick={onIncreaseQuanityClicked}
disabled={product.inventory > 0 ? '' : 'disabled'}> +
</Button>
<Button color="danger"
onclick={onDecreaseQuantityClicked}
disabled={product.inventory > 0 ? '' : 'disabled'}> -
</Button>
<Button onClick={onRemoveFromCartClicked}>Remove</Button>
</CardBody>
</Card>
</div>
)
ProductsContainer.js
const ProductsContainer = ({ products, addToCart }) => (
<ProductsList title="Products">
{products.map(product =>
<ProductItem
key={product.id}
product={product}
onAddToCartClicked={() => addToCart(product.id)}
onIncreaseQuantityClicked={() => increaseQuantity(product.id)}
onDecreaseQuantityClicked={() => decreaseQuantity(product.id)} />
)}
</ProductsList>
)
ProductsContainer.propTypes = {
products: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
title: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
inventory: PropTypes.number.isRequired
})).isRequired,
addToCart: PropTypes.func.isRequired,
increaseQuantity: PropTypes.func.isRequired
}
const mapStateToProps = state => ({
products: getVisibleProducts(state.products)
})
export default connect(
mapStateToProps,
{ addToCart, increaseQuantity, decreaseQuantity }
)(ProductsContainer)
减速器/ products.js
const products = (state, action) => {
switch (action.type) {
case ADD_TO_CART:
return {
...state,
inventory: state.inventory - 1
}
case REMOVE_FROM_CART:
return {
...state,
inventory: state.inventory + 1
}
case INCREASE_QUANTITY:
return {
...state,
//NOT SURE WHAT ELSE TO PUT HERE
}
case DECREASE_QUANTITY:
return {
...state,
NOT SURE WHAT ELSE TO PUT HERE EITHER
}
default:
return state
}
}
有人能指出我正确的道路吗?如果我甚至在正确的道路上,或建议任何可以提供帮助的教程或网站?
答案 0 :(得分:3)
首先,我认为您应该在您的州中加入quantity
,并将数量逻辑与inventory
分开。这是你的州树的样子:
{
cart: [
{id: 1, quantity: 3},
{id: 3, quantity: 2}
],
products: [
{id: 1, inventory: 10, ...},
{id: 2, inventory: 10, ...},
{id: 3, inventory: 10, ...}
]
}
购物车存储添加到购物车中的产品,产品包含所有可用产品。
考虑到这种状态树,我们可以使用以下动作创建者:
function quantityUp(id, val){
return {type: 'QTY_UP', id, up: val}
}
function quantityDown(id, val){
return {type: 'QTY_DOWN', id, down: val}
}
现在,我们可以创建我们的减速器。由于我们将数量与库存分开,我们还应该将减量器分开以反映这种逻辑。
const cart = (state, action) => {
switch(action.type){
case 'QTY_UP':
return Object.assign([], state.map(item => {
if(item.id === action.id){
item.quantity += action.up;
}
return item;
));
case 'QTY_DOWN':
return Object.assign([], state.map(item => {
if(item.id === action.id){
item.quantity -= action.down;
}
return item;
));
default:
return state;
}
};
以下操作也应该是您的购物车减速器的一部分:ADD_TO_CART, REMOVE_FROM_CART
如果需要,产品减速机应注意自行修改产品。一种情况是在购买物品时修改物品的库存。
让我们先创建动作创建者:
//cart will be an array
function purchase(cart){
return {type: 'PURCHASE', cart}
}
现在我们可以创建reducer:
const products = (state, action) => {
switch(action.type){
case 'PURCHASE':
const ids = action.cart.map(item => item.id);
return Object.assign([], state.map(item => {
if(ids.includes(item.id)){
item.inventory -= action.cart.filter(p => p.id === item.id)[0].quantity;
}
return item;
}));
case default:
return state;
}
};
现在,我们可以将产品添加到您的购物车,编辑购物车中每种产品的数量,并在购买产品时更新您所在州的每种产品的库存。
答案 1 :(得分:1)
确保在缩减器之前设置初始状态,如:
const initialState = {
inventory: 0,
quantity: 0
}
然后将您的reducer链接到您刚刚声明的状态:
const products = (state = initialState, action) => {
如果您希望您的操作增加状态数量,请按照库存继续:
quantity: state.quantity + 1
提醒一下,状态首先通过一个或多个reducer启动,然后使用例如
在redux中创建一个商店const store = createStore(yourReducer)
或
const store = createStore(combineReducers(allYourReducers))
您商店的应用程序的全局状态将由您所有reducer的初始状态的总和构成。
然后,您可以通过调度您的操作来访问和播放状态
store.dispatch(yourAction)
如果您的应用中的所有内容都连接良好,您应该可以根据需要更新状态。
您可以从Andrew Mead查看此课程:https://www.udemy.com/react-2nd-edition/learn/v4/overview
答案 2 :(得分:1)
鉴于您当前的代码,addToCart
和increaseQuantity
是相同的。
你可以:
1)重复使用容器中的addToCart
功能
<ProductItem
key={product.id}
product={product}
onAddToCartClicked={() => addToCart(product.id)}
onIncreaseQuantityClicked={() => addToCart(product.id)}
onDecreaseQuantityClicked={() => decreaseQuantity(product.id)} />
2)在reducer中实现相同的逻辑
case INCREASE_QUANTITY:
return {
...state,
inventory: state.inventory - 1
}
答案 3 :(得分:0)
当我们在购物车上工作时,我们应该在购物车状态内拥有cartItems数组,并且每次我们单击“添加到购物车”按钮时,该商品将被推送到该数组,并且我们将在该商品中“映射”该数组我们想要渲染购物车项目的组件。
const INITIAL_STATE = {
//you could have more properties but i focus on cartItems
cartItems: []
};
要将商品添加到购物车,在编写代码时请务必小心。因为第一次将商品添加到购物车很容易,但是如果我们多次将同一商品添加到购物车,该怎么办。因此,我们需要在cartItems数组内对项目进行分组。为此,我们需要编写一个实用函数。
//cart.utils.js
export const addItemToCart = (cartItems, cartItemToAdd) => {
//find(condition) finds the first item in the array based on the condition.
const existingCartItem = cartItems.find(item => item.id === cartItemToAdd.id);
if (existingCartItem) {
//in order for change detection to trigger we have to rerender
//otherwise our quantity property will not be updated
//map will return a new array
//we need to return new versions of our state so that our component know to re render
//here we update the quantity property
return cartItems.map(item =>
item.id === cartItemToAdd.id
? { ...cartItemToAdd, quantity: item.quantity + 1 }
: item
);
}
//when you first time add a new item, sine exixtingCartItem will be falsy, it will pass the first if block and will come here
//quantity property gets attached the first time around since this if block wont run when it is a new item.
//in the beginning cartItems array is empty. every time you add a new item to this array, it will add "quantity:1" to this item object.
return [...cartItems, { ...cartItemToAdd, quantity: 1 }];
};
在化简文件中
从“ ./cart.utils”导入{addItemToCart};
case INCREASE_QUANTITY:
return {
...state,
cartItems: addItemToCart(state.cartItems, action.payload)
};
要从购物车中删除物品,我们需要编写另一个实用程序功能。
cart.utils.js
export const removeItemFromCart = (cartItems, cartItemToRemove) => {
//check if item is already in the cartItems
const existingCartItem = cartItems.find(
item => item.id === cartItemToRemove.id
);
//if there is only 1, upon clicking, we should remove the item from the array
if (existingCartItem.quantity === 1) {
return cartItems.filter(item => item.id !== cartItemToRemove.id);
}
return cartItems.map(item =>
item.id === cartItemToRemove.id
? { ...item, quantity: item.quantity - 1 }
: item
);
};
在reducer / products.js中
import { addItemToCart, removeItemFromCart } from "./cart.utils";
case DECREASE_QUANTITY:
return {
...state,
cartItems: removeItemFromCart(state.cartItems, action.payload)
}