在React

时间:2019-01-25 23:23:37

标签: javascript reactjs

我有一个类组件(实际上是相同组件的集合),其中有2个按钮+和-用于增加和减少手表的数量。手表的最小数量为1,最大数量为10。我已经使用这2个函数gainAmountHandler和reduceAmountHandler对此进行了调节。有了这两个按钮,就可以了。但是问题在于,我必须对父组件中计算出的手表的值求和,并且无法将手表的求和值转发给父组件以声明变量totalAmount。无法使用Redux,因为它是手表组件的集合,并且每个组件都有自己的+和-按钮已被这2个reasureAmountHandler,reducingAmountHandler函数占用。 有人知道如何解决这个问题吗?

子组件:

import React, { Component } from 'react';
import Modal from '.././UI/Modal';

class SelectedWatch extends Component {
    constructor(props) {
        super(props)

        this.state = {
            watchQuantity: 1,
            watchAmount: 1
        }
    }

    increaseAmountHandler = () => {
        if(this.state.watchQuantity < 1) {
            this.setState({
                watchQuantity: 0, 
                watchAmount: 0
            })
            return;
        } else if (this.state.watchQuantity >= 10){
            this.setState({
                watchQuantity: 10,
                watchAmount: this.props.selectedWatch.selectedWatchPrice * this.state.watchQuantity
            })
            return;
        }

        this.setState({
            watchQuantity: this.state.watchQuantity + 1,
            watchAmount: this.props.selectedWatch.selectedWatchPrice * this.state.watchQuantity
        })
    }

    decreaseAmountHandler = () => {
        if(this.state.watchQuantity < 1) {
            this.setState({
                watchQuantity: 0,
                watchAmount: 0
            })
            return;
        } else if (this.state.watchQuantity >= 10){
            this.setState({
                watchQuantity: 9,
                watchAmount: this.props.selectedWatch.selectedWatchPrice * this.state.watchQuantity
            })
            return;
        }

        this.setState({
            watchQuantity: this.state.watchQuantity - 1,
            watchAmount: this.props.selectedWatch.selectedWatchPrice * this.state.watchQuantity
        })
    }

    render() {
        return (
            <div className={"shopping-cart-product" + (this.state.watchQuantity < 1 ? ' notDisplayed' : '')}>
                <div className="product-info">
                    <div>
                        <h3>{this.props.selectedWatch.selectedWatchName}</h3>
                        <p>${this.props.selectedWatch.selectedWatchPrice} &times; {this.state.watchQuantity}</p>
                    </div>
                    <img src={this.props.selectedWatch.selectedWatchUrl} />
                </div>
                <div className="product-count">
                    <button onClick={this.decreaseAmountHandler}>-</button>
                    <span>{this.state.watchQuantity}</span>
                    <button onClick={this.increaseAmountHandler}>+</button>
                </div>
            </div>
        );
    }
}
export default SelectedWatch;

父组件:

import React, { Component } from 'react';
import EnteredWatch from '.././components/EnteredWatch/EnteredWatch';
import SelectedWatch from '.././components/SelectedWatch/SelectedWatch';

class App extends Component {
    constructor(props) {
        super(props)

        this.state = {
            watchName: '',
            watchDescription: '',
            watchUrl: '',
            watchPrice: '',
            watchId: '',
            watchAmount: '',
            watchQuantity: 1, 
            enteredWatchList: [],
            selectedWatchName: '',
            selectedWatchDescription: '',
            selectedWatchUrl: '',
            selectedWatchPrice: '',
            selectedWatchId: '',
            selectedWatchAmount: '', 
            selectedWatchQuantity: 1, 
            selectedWatchList: [],
            totalAmount: 0,
        }
    }

        submitHandler = (event) => {

            event.preventDefault();

            let watchId = Math.floor((Math.random() * 100) + 1);
            let watchName = this.state.watchName;
            let watchDescription = this.state.watchDescription;
            let watchUrl = this.state.watchUrl;
            let watchPrice = this.state.watchPrice;
            let watchQuantity = this.state.watchQuantity;

            this.setState({
                enteredWatchList: this.state.enteredWatchList.concat({watchName, watchUrl, watchDescription, watchPrice, watchId, watchQuantity})
            })

        add = (selectedWatchName, selectedWatchUrl, selectedWatchDescription, selectedWatchPrice, index, selectedWatchQuantity) => {

            let arr = this.state.selectedWatchList;

            let found = arr.some(el => {
                return el.selectedWatchName === selectedWatchName;
            });

            if (!found) { 
                return arr.concat({selectedWatchName, selectedWatchUrl, selectedWatchDescription, selectedWatchPrice, index, selectedWatchQuantity});
            } else {
                return this.state.selectedWatchList;
            }

        }

        buyWatchHandler = (selectedWatchName, selectedWatchUrl, selectedWatchDescription, selectedWatchPrice, index, selectedWatchQuantity) => {

            let arr = this.add(selectedWatchName, selectedWatchUrl, selectedWatchDescription, selectedWatchPrice, index, selectedWatchQuantity);

            this.setState({
                selectedWatchName: selectedWatchName,
                selectedWatchUrl: selectedWatchUrl,
                selectedWatchDescription: selectedWatchDescription,
                selectedWatchPrice: selectedWatchPrice,
                selectedWatchId: index,
                selectedWatchQuantity: selectedWatchQuantity, 
                selectedWatchList: arr
            });
        }

        render() {

            const enteredWatches = this.state.enteredWatchList.map((enteredWatch, index) => {
                return <EnteredWatch
                    key={index}
                    enteredWatch={enteredWatch}
                    selected={this.buyWatchHandler.bind(this, enteredWatch.watchName, enteredWatch.watchUrl,
                        enteredWatch.watchDescription, enteredWatch.watchPrice, index, enteredWatch.watchQuantity)}
                />
            });

            const selectedWatches = this.state.selectedWatchList.map((selectedWatch, index) => {
                const active = this.state.activeIndex;
                return <SelectedWatch
                    key={index}
                    active={index === active}
                    selectedWatch={selectedWatch}
                />
            });

            return (
                <div className="App">
                    <div className="container-fluid">
                        <div className="container">
                            <div className="add-product">
                               <form>
                                    <div>
                                        <label>Product name:</label>
                                        <input 
                                            type="text" 
                                            placeholder="Casio Watch" 
                                            required
                                            value={this.state.watchName}
                                            onChange={event => this.setState({watchName: event.target.value})}
                                        />
                                    </div>

                                    <div>
                                        <label>Product description:</label>
                                        <textarea 
                                            placeholder="Sample description..."
                                            value={this.state.watchDescription}
                                            onChange={event => this.setState({watchDescription: event.target.value})}
                                        >
                                        </textarea>
                                    </div>

                                    <div>
                                        <label>Product image:</label>
                                        <input 
                                            type="text" 
                                            placeholder="http://...jpg"
                                            value={this.state.watchUrl}
                                            pattern="https?://.+" required
                                            onChange={event => this.setState({watchUrl: event.target.value})}
                                        />
                                    </div>

                                    <div>
                                        <label>Product price:</label>
                                        <input 
                                            type="number" 
                                            min="0" 
                                            placeholder="22" 
                                            value={this.state.watchPrice}
                                            onChange={event => this.setState({watchPrice: event.target.value})}
                                        />
                                    </div>

                                    <button
                                        type="submit"
                                        onClick={event => this.submitHandler(event)}
                                    >
                                        Add a new Task
                                    </button>
                                </form>
                             </div>

                             <div className="list-products">
                                <ul>
                                   {enteredWatches}
                                </ul> 
                            </div>

                            <div className="shopping-cart">
                                <div className="shopping-cart-products">
                                    <ul>
                                       {selectedWatches}
                                    </ul> 

                                </div>
                                <div className="shopping-cart-summary">
                                    <div>Total: <b>${this.state.totalAmount}</b></div>
                                    <div><button onClick={this.summaryHandler}>Purchase</button></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            );
        }
    }

    export default App;

1 个答案:

答案 0 :(得分:1)

父母必须跟踪添加了多少只手表。

使父母变得聪明(有状态),让孩子变得愚蠢(无状态)。 管理父级中的所有状态,并将点击处理程序也置于父级中。

将这些处理程序传递给孩子,单击该孩子的按钮时将其解雇。像这样:

class Parent extends React.Component {
  this.state = {
    cart: [],
    watches: [
      { id: 1, name: "Casio", description: "...", price: 25 },
      { id: 2, name: "Rolex", description: "...", price: 3000 },
      { id: 3, name: "Timex", description: "...", price: 10 },
    ],
  }

  handleClickIncrement = (watchId) => {
    //add it to the cart (or increment it if its already there)
  }

  handleClickDecrement = (watchId) => {
    //remove it from the cart (or deccrement it if its already there)
  }

  getCartTotal() {
    //loop over cart and calculate
  }

  renderWatches() {
    this.state.watches.map(watch => (
      <Watch id={watch.id}
        name={watch.name}
        description={watch.description}
        price={watch.price}
        onClickIncrement={() => { this.handleClickIncrement(watch.id); }} 
        onClickDecrement={() => { this.handleClickDecrement(watch.id); }} 
    ))
  }

  render() {
    <div>
      <h1>Our selection of watches:</h1>
      {this.renderWatches()}

      <h1>Your cart total: {this.getCartTotal()}</h1>
    </div>
  }
}


class Watch extends React.Component {
  props = {
    id,
    name,
    description,
    price,
    quantityInCart,
    onClickIncrementButton,
    onClickDecrementButton
  }

  render() {
    <div>
      <h1>{this.props.name}</h1>
      <p>{this.props.description}</p>
      <h5>${this.props.price}</h5>
      <button onClick={this.props.onClickIncrementButton}>+</button>
      <button onClick={this.props.onClickDecrementButton}>-</button>
    </div>
  }
}