javascript - redux 和反应不需要的效果
问题描述
大家好
- 我正在尝试使用 redux 制作购物车功能。
2.问题描述:
问题是,一旦我想从我的购物篮中取出不是最后一个产品。
Redux 确实从商店中删除了所需的产品,但在前端我仍然看到该产品并做出反应从列表中删除最后一个产品(我不想删除的那个)。
我必须转到另一个页面而不重新加载并返回购物篮才能看到对重置的反应
如果我从列表中删除最后一个产品,则删除工作正常。
我制作了一个由谷歌驱动器提供的视频链接:
https://drive.google.com/file/d/1miZA4B1Ay5OZZBGPj1bCcQHsGv21oVW_/view
这是我想要或期望拥有的 redux 效果(这是从购物车列表中删除最新产品的操作:
如果我的购物车中有多个产品,而我只想删除一个产品而不是最后一个(不需要的效果):
ADD_TO_CART_ACTIONdispatch
store.dispatch({
type: ADD_PRODUCT_TO_CART_ACTION,
payload: {
data: {
productID: data.product.id,
attributeID: RadioState,
price: data.price,
quantity: 1
}
}
})
这是我的购物车减速器:
export function CartReducer(state = [], action){
const cart = [...state]
switch (action.type){
case 'ADD_PRODUCT_TO_CART_ACTION':
return [...state, {...action.payload.data}];
case 'UPDATE_QUANTITY_FROM_CART_ACTION':
return cart.map(product => {
if (product.attributeID === action.payload.attributeID){
product.quantity++
return {...product}
} else {
return product
}
})
case 'REMOVE_QUANTITY_FROM_CART_ACTION':
return cart.map(product => {
if (product.attributeID === action.payload.attributeID){
product.quantity--
return {...product}
} else {
return product
}
})
case 'TRASH_PRODUCT_FROM_CART_ACTION':
return cart.filter(product => product.attributeID !== action.payload)
default:
return state;
}
}
这是他们首先从 redux 连接的购物车组件:
export function Cart (props)
{
const [productCount, setProductCount] = useState(0)
useEffect(() => {
setProductCount(props.count)
}, [])
if (props.cart.length === 0){
return <div className="home"><p className={'text-center text-green-500'}>Add product to cart.</p></div>
}
return (
<React.Fragment className="home">
<Grid container spacing={3}>
{props.cart.map((item, index) => {
return (
<Grid item xs={6}>
<ProductCartDetails productCount={productCount} key={index} attributes={item}/>
</Grid>
)
})}
</Grid>
</React.Fragment>
)
}
export const CartStore = connect(
(state) => ({
cart: cartSelectors(state),
count: cartCount(state)
})
)(Cart)
这是 ProductCartDetails (产品的卡片,这里是派发的动作)
export default function ProductCartDetails (props){
const [productCount, setProductCount] = useState(0)
const [product, setProduct] = useState([])
const [requestReady, setRequestReady] = useState(false)
useEffect(() => {
axios.get(`product/${props.attributes.productID}`)
.then(({data}) => {
setProduct(data)
setRequestReady(! requestReady)
})
.catch((err) => {
console.log(err)
})
}, [props.productCount])
useEffect(() => {
setProductCount(props.productCount)
}, [props.productCount])
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
width: "100%",
marginTop: 4,
backgroundColor: "#faf7f7",
boxSizing: 'border-box',
},
details: {
display: 'flex',
flexDirection: 'column',
},
content: {
flex: '1',
},
cover: {
width: 151,
height: '100%'
},
}));
const onClickAddMoreQuantity = () => {
let cart = [...store.getState()]
let updatedQuantity = false;
cart.map(product => {
if (product.attributeID === props.attributes.attributeID){
store.dispatch(
{
type: UPDATE_QUANTITY_FROM_CART_ACTION,
payload: {
attributeID: props.attributes.attributeID
}
}
)
updatedQuantity = true
}
})
if (updatedQuantity === false){
swal({
icon: 'error',
title: 'Cart',
text: 'Product quantity cannot be bigger than the product stock.',
})
}
}
const onClickRemoveQuantityFromCart = () => {
let cart = [...store.getState()]
let updatedQuantity = false;
cart.map(product => {
if (product.attributeID === props.attributes.attributeID){
store.dispatch(
{
type: REMOVE_QUANTITY_FROM_CART_ACTION,
payload: {
attributeID: props.attributes.attributeID
}
}
)
updatedQuantity = true
}
})
if (updatedQuantity === false){
swal({
icon: 'error',
title: 'Cart',
text: 'Product quantity has not been removed.',
})
}
}
const onClickTrashProductFromCart = () => {
let cart = [...store.getState()]
let updatedQuantity = false;
cart.map(product => {
if (product.attributeID === props.attributes.attributeID){
store.dispatch(
{
type: TRASH_PRODUCT_FROM_CART_ACTION,
payload: props.attributes.attributeID
}
)
updatedQuantity = true
}
})
if (updatedQuantity === false){
swal({
icon: 'error',
title: 'Cart',
text: 'Product has not been removed.',
})
}
}
const classes = useStyles();
if (productCount !== 0){
return (
<>
<Card className={classes.root}>
<Link to={requestReady ? `/details/${product.slug}` : null}>
<img
className={classes.cover}
src={requestReady ? axios.defaults.baseURL+product.image[0].url+"?h=600" : null}
alt="image cover product cart"
/>
</Link>
<div className={classes.details}>
<CardContent className={classes.content}>
<Typography className="text-center text-gray-700" component="h6" variant="h6">
{requestReady ? product.name : null}
</Typography>
<p className="text-center text-gray-600">
Details Of Product
</p>
<div>
<Typography variant="subtitle1" color="textSecondary">
Category: {requestReady ? product.category.label : null}
</Typography>
<Typography variant="subtitle1" color="textSecondary">
<ProductCartAttributeDetails attributes={props.attributes} />
</Typography>
</div>
</CardContent>
<CardActions>
<button id={requestReady ? product.id : null} onClick={onClickAddMoreQuantity}>
<Add height={10} />Add quantity
</button>
<button>
<Delete height={10} onClick={onClickTrashProductFromCart} />Trash
</button>
<button onClick={onClickRemoveQuantityFromCart}>
<Remove height={10} />Remove quantity
</button>
</CardActions>
</div>
</Card>
</>
)
} else {
return (
<>
<Card className={classes.root}>
<Link to={requestReady ? `/details/${product.slug}` : null}>
<img
className={classes.cover}
src={requestReady ? axios.defaults.baseURL+product.image[0].url+"?h=600" : null}
alt="image cover product cart"
/>
</Link>
<div className={classes.details}>
<CardContent className={classes.content}>
<Typography className="text-center text-gray-700" component="h6" variant="h6">
{requestReady ? product.name : null}
</Typography>
<p className="text-center text-gray-600">
Details Of Product
</p>
<div>
<Typography variant="subtitle1" color="textSecondary">
Category: {requestReady ? product.category.label : null}
</Typography>
<Typography variant="subtitle1" color="textSecondary">
<ProductCartAttributeDetails attributes={props.attributes} />
</Typography>
</div>
</CardContent>
<CardActions>
<button id={requestReady ? product.id : null} onClick={onClickAddMoreQuantity}>
<Add height={10} />Add quantity
</button>
<button>
<Delete height={10} onClick={onClickTrashProductFromCart} />Trash
</button>
<button onClick={onClickRemoveQuantityFromCart}>
<Remove height={10} />Remove quantity
</button>
</CardActions>
</div>
</Card>
</>
)
}
}
如果ProductCartAttributeDetails
需要
export default function ProductCartAttributeDetails({attributes}){
const [attribute, setAttribute] = useState([])
const [requestReady, setRequestReady] = useState(false)
useEffect(() => {
axios.get(`attributes/${attributes.attributeID}`)
.then(({data}) => {
setAttribute(data)
setRequestReady(! requestReady)
})
.catch((err) => {
console.log(err)
})
}, [])
return (
<>
<Typography variant="subtitle1" color="textSecondary">
<p><span className="capitalize">{requestReady ? attribute.attribute : null}</span> : {requestReady ? attribute.value : null}</p>
</Typography>
<Typography variant="subtitle1" color="textSecondary">
<p>Quantity: {requestReady ? attributes.quantity : null}</p>
</Typography>
<Typography variant="subtitle1" color="textSecondary">
<p>Total Price: {requestReady ? attribute.price * attributes.quantity : null}</p>
</Typography>
</>
)
}
解决方案
通过您自己的索引更改 React js 的默认索引来解决问题,对我来说,我使用从我的商店收到的索引来确保它们是唯一的
推荐阅读
- python - 通过更新塑性应变分量在 Abaqus 中进行迭代计算?
- sql - 创建一个函数以返回电影名称
- python - 如何使用熊猫重塑数据表的特定列?
- javascript - Redux store.dispatch 目的
- loops - 比较两个 XML 文件并在 XSLT 中获得相同的值
- python - 尝试从终端运行功能文件时出现未找到模块错误
- reactjs - 关于 mapDispatchToProps 和 bindActionCreators 在 multipla 动作时的问题
- python - 如何在另一台计算机上使用通过python连接的MySQL数据库?
- python - 具有 5 个参数的 Python 多处理
- python - Python中带有model.fit函数的“帮助”