如何使用React Redux状态有条件地显示和禁用按钮

问题描述 投票:1回答:3

我已经用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)));

我似乎无法将其包裹起来。我希望你们能提供帮助。

提前感谢。

reactjs redux shopping-cart
3个回答
1
投票

您可以使用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/>}

让我知道您是否还有其他问题。

我将尝试解决它们


0
投票

在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>

0
投票

您可以通过检查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>
© www.soinside.com 2019 - 2024. All rights reserved.