如何为每个元素填充单独的“增量”和“减量”按钮?

时间:2019-01-14 13:59:19

标签: reactjs button increment

enter image description here

你好,我正在尝试开发一个简单的购物车演示。我在react中使用map函数来遍历一个json文件.JSON数据可以正常显示,但是单击递增按钮会更改所有产品的所有值如何填充单个递增按钮和div表示每个元素的数量?

注意:最后我想在总价格的右上方显示总金额吗?

header.js

import React, { Component } from "react";

class header extends Component {
    state = {
        totalcount: 2
    };
    render() {
        return (
            <div>
                <nav className="navbar navbar-expand-lg navbar-dark bg-info">
                    <a className="navbar-brand" href="#">
                        <img src="./logo.png" id="logo" alt="" />
                    </a>
                    <button
                        className="navbar-toggler"
                        type="button"
                        data-toggle="collapse"
                        data-target="#navbarNavDropdown"
                        aria-controls="navbarNavDropdown"
                        aria-expanded="false"
                        aria-label="Toggle navigation"
                    >
                        <span className="navbar-toggler-icon" />
                    </button>
                    <div className="collapse navbar-collapse" id="navbarNavDropdown">
                        <ul className="navbar-nav">
                            <li className="nav-item active">
                                <a className="nav-link" href="#">
                                    Home <span className="sr-only">(current)</span>
                                </a>
                            </li>
                            <li className="nav-item">
                                <a className="nav-link" href="#">
                                    Features
                </a>
                            </li>
                            <li className="nav-item">
                                <a className="nav-link" href="#">
                                    Pricing
                </a>
                            </li>

                        </ul>


                    </div>
                    <input className="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"></input>
                    <button className="btn btn-success m-2" type="submit">Search</button>
                    <h2><span className={this.getClass()}>
                        Total Price: {this.formatCount()}
                    </span></h2>

                </nav>
            </div>
        );
    }
    getClass() {
        let classes = "badge";
        classes += this.state.count === 0 ? " badge-danger" : " badge-warning";
        return classes;
    }

    formatCount() {
        const { totalcount } = this.state;
        return totalcount === 0 ? "0 %n  Your Cart is Empty" : totalcount;
    }
}

export default header;

index.js

import React from "react";
import ReactDOM from "react-dom";
import Main from "./components/main.js";
import Footer from "./components/footer.js";
import Header from "./components/header.js";
import './index.css';
import 'bootstrap/dist/css/bootstrap.css';


ReactDOM.render(<Main />, document.getElementById("root"));
ReactDOM.render(<Header />, document.getElementById("header"));
ReactDOM.render(<Footer />, document.getElementById("footer"));

main.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import ProductInfo from '../plist.json'


class Products extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  handleIncerement() {
    this.setState({
      count: this.state.count + 1
    });
  }

  handleDecrement() {
    this.setState({
      count: this.state.count - 1
    });
  }

  render() {
    return (

        <div className="container">
          <div className="row ">
            {ProductInfo.map((postDetail, index) => {
              return (


                  <div className="col-md-4 ml-auto">

                    <a href="require(`${postDetail.url}`)"><img className="productpic" src={require(`./${postDetail.image}`)} /></a>
                    <h2 className="display-6"> <a href="{postDetail.url}">{postDetail.name}</a></h2>
                    <p className="h4">{postDetail.price}</p>
                    <p className="info">{postDetail.description}</p>
                    <div className="counter">


                        <button className="btn btn-info" onClick={() => this.handleIncerement()}>+</button>
                        <div>{this.state.count}</div>
                        <button className="btn btn-info" onClick={() => this.handleDecrement()}>-</button>

                    </div>
                  </div>

              )
            })}
          </div>
        </div>

    )
  }
}

export default Products

这是我的CSS

body {
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
    "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

}
#root{
  background-color: #f1f1f1;
}

a .nav-link{
  font-size:4rem;
}

.form-control{
  width:50vh !important;  
}

#logo{
  height:5rem;
}

.nav-item{
  font-size:2rem;
  font-weight:500;
}

.row{
 padding:15vh 0 10vh 0;
}
.row blockquote,p, h2{

  text-align: center;
  font-size:0.9rem;
}
.col-md-4{
  background-color:white;
  max-width:30vh !important;
  display: block;
  margin:0 4vh 7vh 0;  
  padding:5vh 0 5vh 0;
  -moz-box-shadow:    1px 1px 4px 4px #ccc;
  -webkit-box-shadow: 1px 1px 4px 4px #ccc;
  box-shadow:         1px 1px 4px 4px #ccc;

}

.info{
  min-height:12vh;
}

a{
  text-decoration: none;

}
.productpic{
  width:150px;
  height:150px;

  margin: auto;
  display: block;

}
.display-6 a:link{
    text-decoration: none !important;    
    color:lightgray !important;
}

.display-6 a:hover{
  color:#161616 !important;

  font-weight:650 !important;
}

.container{
  margin:auto;
  padding:0;
  background-color:E0E0E0;
}

.blockquote{
  font-size:0.8rem !important;
  max-width:25vh;
  text-align:center;

}
.counter{
  text-align:center;
  display:block;

}

1 个答案:

答案 0 :(得分:-1)

在产品处于阵列状态时,您可以使用单个count键来存储数据。 这意味着,您的产品基本上都引用相同的计数。 处理它的最好方法是创建一个Product组件,该组件处理自己的计数器。

class Product extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0, totalPrice: 0 }; 
  }
  handleIncrement = () => {
    const { count, totalPrice } = this.state;
    const { price, increaseTotals } = this.props; 
    const newCount = count + 1;
    const newTotal = newCount * price;
    this.setState({ count: newCount, totalPrice: newTotal }, () => {
      increaseTotals(price);
    });
  }
  handleDecrement = () => {
    const { count, totalPrice } = this.state;
    const { price, decreaseTotals } = this.props; 
    const newCount = count - 1;
    const newTotal = newCount * price;
    this.setState({ count: newCount, totalPrice: newTotal }, () => {
      decreaseTotals(price);
    });
  }
  render() {
    const { url, name, image, price, description } = this.props;
    return (
      <div className="col-md-4 ml-auto">
        <a href="require(`${url}`)"><img className="productpic" src={require(`./${image}`)} /></a>
        <h2 className="display-6"> <a href="{url}">{name}</a></h2>
        <p className="h4">{price}</p>
        <p className="info">{description}</p>
        <div className="counter">
          <button className="btn btn-info" onClick={this.handleIncerement}>+</button>
          <div>{this.state.count}</div>
          <button className="btn btn-info" onClick={this.handleDecrement}>-</button>
        </div>
      </div>
    );
  }
}

然后在您的Products组件中实现它:

class Products extends React.Component {
  constructor(props) {
    super(props);
    this.state = { totalCount: 0, totalPrice: 0 };
  }
  increaseTotals = price => {
    const { totalCount, totalPrice } = this.state;
    const newCount = totalCount + 1;
    const newPrice = newCount * price;
    this.setState({ totalCount: newCount, totalPrice: newPrice }); 
  }
  decreaseTotals = price => {
    const { totalCount, totalPrice } = this.state;
    const newCount = totalCount - 1;
    const newPrice = newCount * price;
    this.setState({ totalCount: newCount, totalPrice: newPrice }); 
  }
  render() {
    return (
      <div className="container">
        <div className="row ">
          {ProductInfo.map(postDetail => (
            <Product
              increaseTotals={this.increaseTotals}
              decreaseTotals={this.decreaseTotals}
              {...postDetail}
            />
          )}
        </div>
      </div>
    );
  }
}

它将所需的数据封装在子组件中,从而解决您的问题,并使您的代码更易于重新实现。