反应如何更新所点击的项目的道具,而不是所有项目

时间:2015-08-27 14:20:34

标签: jquery reactjs

我在更新React中的值时遇到问题。我还要说明我是一个反应迟钝的小伙子,并且仍然试图掌握一些概念。

我有一个组件,在单击时递增和递减值。问题是它更新了所有项目的所有道具而不是单击的道具。

例如,我有一个项目列表,我点击1项来更新它所做的quantity,但也会更新其他项目的数量。所有这些项目都很相似。还需要做的是,它应该计算所有项目的所有数量,并输出一个不起作用的总数。

这是一张带有我正在努力完成的注释的图片:

http://i.imgur.com/HlhPcym.png

非常感谢任何帮助。

数量组件:

import React from 'react';
import If from '../utils/helpers';


var QuantityInput = React.createClass({
  getInitialState: function(props) {
    return {
      quantity: this.props.quantity
    };
  },

  handleIncrement: function(e) {
    this.props.handleIncrement(this.props.quantity + 1);
  },

  handleDecrement: function(e) {
    if (this.props.quantity > 1) {
      this.props.handleDecrement(this.props.quantity - 1);
    }
  },

  handleChange: function(e) {
    this.setState({
      quantity: this.props.quantity
    });
  },

  render: function() {
    return (
      <div className="quantity-input">
        <span className="button button--gray controls__quantity" onClick={this.handleDecrement}>-</span>
        <div className="quantity" onChange={this.handleChange}>{this.props.quantity}</div>
        <span className="button button--gray controls__quantity" onClick={this.handleIncrement}>+</span>
      </div>
    );
  }
});

module.exports = QuantityInput;

产品:

import React from 'react';
import If from '../utils/helpers';
import QuantityInput from '../components/quantity.js'


var Product = React.createClass({
  getInitialState: function() {
    return {
      quantity: 0
    }
  },

  handleIncrement: function(e) {
    this.setState({
      quantity: this.state.quantity + 1
    });
  },

  handleDecrement: function(e) {
    if (this.state.quantity > 1) {
      this.setState({
        quantity: this.state.quantity - 1
      });
    }
  },

  handleChange: function(e) {
    var value = e.target.value.replace(/[^0-9]/, '');

    value = (value == '' ? 1 : value);
    value = parseInt(value);

    this.setState({
      quantity: value
    });
  },

  render: function() {
    var content;
    var self = this;
    if (this.props.items.length > 0) {
      this.props.items.map(function(product) {
        var items = product.priceCode.map(function(priceCode) {
          return (
            <div className="list-item" key={priceCode.priceCode_id}>
              <div className="list-info list-info--cart">
                <div className="list-info__venue">
                  <h3 className="event-title">{priceCode.priceCode_title}</h3>
                  <If condition={priceCode.priceCode_passcode}>
                    <input type="text" placeholder="Passcode" />
                  </If>
                  <span className="event-details">{priceCode.priceCode_info}</span>
                </div>
              </div>
              <div className="controls">
                <div className="list-info__price">${priceCode.priceCode_price}</div>
                <QuantityInput quantity={self.state.quantity} handleChange={self.handleChange} handleIncrement={self.handleIncrement} handleDecrement={self.handleDecrement} />
              </div>
            </div>
          )
        });

        content = {items}
      });
    }

    return (
      <div>
        {content}
      </div>
    );
  }
});

var ProductContainer = React.createClass({
  getInitialState: function() {
    return {
      data: [],
      quantity: 0
    }
  },

  componentWillMount: function() {
    this.loadProducts(this.props.url);
  },

  loadProducts: function(url) {
    $.ajax({
      url: url,
      dataType: 'json',
      success: function(data) {
        this.setState({
          data: data
        });
      }.bind(this),
      error: function(xhr, status, err, data) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },

  _hasData: function() {
    var displayedItems = this.state.data.filter(function(product) {
      var match = product.priceCode.filter(function(priceCode) {
        return priceCode.priceCode_title.toLowerCase();
      });

      return (match !== -1);
    }.bind(this));

    return (
      <div>
        <Product items={displayedItems} />
      </div>
    ); 
  }, 

  render: function() {
    if (this.state.data) {
      return (
        <div className="price-code">
          {this._hasData()}
          <div className="subtotal-wrapper">
            <a href="#" className="button button--gray">Clear Selections</a>
            <div className="subtotal">
              Subtotal ({this.state.quantity}):
            </div>
            <a href="#" className="button">Find Tickets</a>
          </div>
        </div>
      )          
    } else {
      return <div>Loading...</div>;
    }

    return false
  }
});

module.exports = ProductContainer;

1 个答案:

答案 0 :(得分:2)

由于您QuantityInput组件quantity状态通过Product,因此quantity组件将会收到相同的quantity

顺便说一句,你不区分每个[...],这非常令人困惑。这是一种做法:

我不会创建详细的实现,但这里是要点(var ProductContainer = React.createClass({ getInitialState: function() { return { data: [], subTotal: 0 } }, incrementSubTotal: function() { this.setState({ data: this.state.data, subTotal: this.state.subTotal + 1 }); }, decrementSubTotal: function() { this.setState({ data: this.state.data, subTotal: this.state.subTotal - 1 }); }, _hasData: function() { [...] return ( <div> <Product items={displayedItems} incrementSubTotal={this.incrementSubTotal} decrementSubTotal={this.decrementSubTotal}/> </div> ); }, render: function() { [...] Subtotal ({this.state.subTotal}): [...] } }); 表示您的代码保持不变):

ProductContainer

var Product = React.createClass({
  //this component is now stateless

  render: function() {
    [...]

    // the following extract items from within this.props and lets the 'incrementSubTotal' and
    // 'decrementSubTotal' in '...callbacks'. See http://facebook.github.io/react/docs/transferring-props.html
    // for details.
    var {items, ...callbacks} = this.props;
    [...]
        <QuantityInput {...callbacks}/>
    [...]

    return (
      <div>
        {content}
      </div>
    );
  }
});

产品

var QuantityInput = React.createClass({

  getInitialState: function() {
    return {
      quantity: 0
    }
  },

  handleIncrement: function(e) {
    [...]
    this.props.incrementSubTotal();
  },

  handleDecrement: function(e) {
    [...]
    this.props.decrementSubTotal();
  },

  render: function() {
    return (
      <div className="quantity-input">
        <span className="button button--gray controls__quantity" onClick={this.handleDecrement}>-</span>
        <div className="quantity">{this.state.quantity}</div>
        <span className="button button--gray controls__quantity" onClick={this.handleIncrement}>+</span>
      </div>
    );
  }
});

QuantityInput

-Wshadow

正如您所看到的,我通过回调来更新子组件中父组件的状态。 这不是一个很好的做法。更好的方法是将所有输入的状态保持在顶级组件上,充当&#34;控制器视图&#34;组件,如果你对MVC模型了解一点。 点击&#34; +&#34;或&#34; - &#34;按钮,您的应用程序应触发一个事件,让ProductContainer知道某些内容已发生变化,并且必须更新它的状态。而且它恰好是(Flux)[https://facebook.github.io/flux/]架构的作用,您应该明确地看一下它。)