Как заполнить отдельные кнопки Incerement и Decrement для каждого элемента? - PullRequest
0 голосов
/ 14 января 2019

enter image description here

Здравствуйте. Я пытаюсь разработать простую демонстрацию корзины покупок. Я перебираю json-файл, используя функцию map в реагировать. Данные 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 голосов
/ 14 января 2019

Вы используете один ключ 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>
    );
  }
}

Это решит вашу проблему за счет инкапсуляции необходимых данных в дочерних компонентах и ​​упростит повторную реализацию кода.

...