我已经用React-Redux制成了购物车。一切正常,但是我正在为一件特别的事情而苦苦挣扎。将项目添加到购物车后,即更改了“添加到购物车”按钮。我希望此按钮被禁用,或者在“删除项目”按钮中更改此按钮。
添加项目后如何更改?
我的减速器(“ ADD_TO_CART”和“ REMOVE_ITEM”):
import bg6 from '../../images/bg6.svg'
import bg7 from '../../images/bg7.svg'
import bg8 from '../../images/bg8.svg'
const initState = {
items: [
{ id: 1, title: 'Landing Page', desc: "Template", price: 10, img: bg6 },
{ id: 2, title: 'Adidas', desc: "Lore", price: 10, img: bg7 },
{ id: 3, title: 'Vans', desc: "Lorem ip", price: 10, img: bg8 },
],
addedItems: [],
total: 0,
}
const cartReducer = (state = initState, action) => {
if (action.type === "ADD_TO_CART") {
let addedItem = state.items.find(item => item.id === action.id)
//check if the action id exists in the addedItems
let existed_item = state.addedItems.find(item => action.id === item.id)
if (existed_item) {
addedItem.quantity = 1
return {
...state,
total: state.total + addedItem.price
}
}
else {
let addedItem = state.items.find(item => item.id === action.id)
addedItem.quantity = 1;
//calculating the total
let newTotal = state.total + addedItem.price
return {
...state,
addedItems: [...state.addedItems, addedItem],
total: newTotal
}
}
}
if (action.type === "REMOVE_ITEM") {
let itemToRemove = state.addedItems.find(item => action.id === item.id)
let new_items = state.addedItems.filter(item => action.id !== item.id)
//calculating the total
let newTotal = state.total - (itemToRemove.price * itemToRemove.quantity)
return {
...state,
addedItems: new_items,
total: newTotal
}
}
else {
return state
}
}
export default cartReducer
My Home Component where i want to change the button:
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { addToCart, removeItem } from '../../../store/actions/cartActions'
import { withStyles } from '@material-ui/core/styles';
import { Link, Redirect, withRouter, generatePath } from 'react-router-dom'
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import CssBaseline from '@material-ui/core/CssBaseline';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import Container from '@material-ui/core/Container';
import Button from '@material-ui/core/Button';
import Card from '@material-ui/core/Card';
import Appbar from '../../home/Appbar'
import CheckIcon from '@material-ui/icons/Check';
import DeleteIcon from '@material-ui/icons/Delete';
const styles = theme => ({
main: {
backgroundColor: '#121212',
maxHeight: 'auto',
width: '100%',
padding: '0',
margin: '0',
},
cardGrid: {
height: "auto",
paddingTop: theme.spacing(8),
paddingBottom: theme.spacing(8),
},
card: {
backgroundColor: "#272727",
height: '100%',
display: 'flex',
flexDirection: 'column',
},
cardMedia: {
paddingTop: '56.25%', // 16:9
},
cardContent: {
flexGrow: 1,
},
});
class Home extends Component {
render() {
const { classes, items, addedItems, addedItemID } = this.props
const { } = this.state
console.log(addedItemID)
let allItems =
items.map(item => {
return (
<Grid item key={item.id} xs={12} sm={6} md={4}>
<Card className={classes.card}>
<CardMedia
className={classes.cardMedia}
image={item.img}
alt={item.title}
title={item.title}
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant="h5" component="h2">
{item.title} {item.price}
</Typography>
<Typography>
{item.desc}
</Typography>
</CardContent>
<CardActions className={classes.cardActions}>
<Button
onClick={() => { this.props.addToCart(item.id) }}
style={{ color: "#d84", border: "1px solid #d84" }}
size="small"
color="primary"
disables={} //// HERE I NEED TO DISABLE BUTTON WHEN ITEM IS ADDED ////
>
Add to Cart //// THIS NEEDS TO BE DELETE ITEM ////
</Button>
</CardActions>
</Card>
</Grid>
)
})
return (
<React.Fragment>
<CssBaseline />
<Appbar />
<main className={classes.main}>
<Container className={classes.cardGrid} maxWidth="lg">
<Grid container spacing={4}>
{allItems}
</Grid>
</Container>
</main>
</React.Fragment>
)
}
}
const mapStateToProps = (state) => {
return {
items: state.cartReducer.items,
addedItems: state.cartReducer.addedItems,
addedItemID: state.cartReducer.addedItemID,
}
}
const mapDispatchToProps = (dispatch) => {
return {
addToCart: (id) => { dispatch(addToCart(id)) },
removeItem: (id) => { dispatch(removeItem(id)) },
}
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(Home)));
我似乎无法将其包裹起来。我希望你们能提供帮助。
提前感谢。
您可以使用this.props.addedItems并检查其中是否包含您当前要添加的项目,添加一种方法并将其用于Disabled State。
const isItemExist = (itemToFindId) => {
return this.props.addedItems.findIndex(item => item.id === itemToFindId) === -1;
}
<Button
onClick={() => { this.props.addToCart(item.id) }}
style={{ color: "#d84", border: "1px solid #d84" }}
size="small"
color="primary"
disables={()=>isItemExist(item.id)} //// HERE I NEED TO DISABLE BUTTON WHEN ITEM IS ADDED ////
>
Add to Cart //// THIS NEEDS TO BE DELETE ITEM ////
</Button>
您也可以使用相同的逻辑并创建另一个按钮使用
{isItemExist(item.id) ? <RemoveCartButton/> : <AddToCartButton/>}
让我知道您是否还有其他问题。
我将尝试解决它们
在JSX中使用条件渲染:首先使其他状态用于处理按钮的状态。我称之为“ is_add_to_cart”,每次在两个减速器部分中单击按钮时,我们都应将is_add_to_cart的值更改为相反的值我的意思是,如果您最初将init状态的is_add_to_cart : true
设置为初始值,则应恢复其值,并且应该是这样的:处于新状态的is_add_to_cart = !is_add_to_cart
。
作为jsx代码的返回部分,我们应该进行条件渲染,因此这里看起来是这样:
is_add_to_cart ? <Button . . . >Add To Cart</Button>
: <Button . . . >Delete Item</Button>
您可以通过检查addedItems
长度或total
的值来做到这一点。首先,在total
函数中包含mapStateToProps
:
const mapStateToProps = (state) => {
return {
items: state.cartReducer.items,
addedItems: state.cartReducer.addedItems,
addedItemID: state.cartReducer.addedItemID,
total: state.cartReducer.total
}
}
然后从组件的道具中提取它:
const { classes, items, addedItems, addedItemID, total } = this.props;
现在您的按钮可以是这样的:
<Button
onClick={() => { this.props.addToCart(item.id) }}
style={{ color: "#d84", border: "1px solid #d84" }}
size="small"
color="primary"
disabled={total > 0 || addedItems.length > 0 ? true : false}
>
{total > 0 || addedItems.length > 0 ? "Delete Item" : "Add to Cart" }
</Button>