【问题标题】:Pass multiple parameters to event handlers in React将多个参数传递给 React 中的事件处理程序
【发布时间】:2017-08-26 14:09:46
【问题描述】:

所以我试图让 react 使用 ES6 语法。在 ES5 中,我有 setInitialState 没有使用函数绑定语法的构造函数。我有一个任意价格列表,我希望在输入元素更改时更改状态。但正确的价格必须改变。

我什至不太确定这是正确的做法。有人可以告诉我最近应该做的方式吗?

这是我的代码:

import React, {Component} from 'react'
import 'bootstrap/dist/css/bootstrap.css';

export default class PriceTable extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      pid: this.props.pid || "12345",
      name: this.props.name || "name",
      prices: this.props.prices || [
        {count: 1, desc: 'one', price: 8.25},
        {count: 6, desc: 'six', price: 7.60},
        {count: 12, desc: 'twelve', price: 6.953}
      ]
    };

    this.setPid = this.setPid.bind(this);
    this.setName = this.setName.bind(this);
    this.setCount = this.setCount.bind(this, i);
    this.setDesc = this.setDesc.bind(this, i);
    this.setPrice = this.setPrice.bind(this, i);
    this.logDebug = this.logDebug.bind(this);
  }

  setPid(e) {
    this.setState({pid: e.target.value})
  }

  setName(e) {
    this.setState({name: e.target.value})
  }

  setCount(i, e) {
    var newPrices = this.state.prices
    newPrices[i].count = e.target.value
    this.setState({prices: newPrices})
  }

  setDesc(i, e) {
    var newPrices = this.state.prices
    newPrices[i].sec = e.target.value
    this.setState({prices: newPrices})
  }

  setPrice(i, e) {
    var newPrices = this.state.prices
    newPrices[i].price = e.target.value
    this.setState({prices: newPrices})
  }

  _renderPriceRow(price, i) {
    return (
      <tr key={i}>
        <td >
          <input type="text" className="form-control" defaultValue={price.count} onChange={this.setCount(this, i).bind(this, i)}/>
        </td>
        <td >
          <input type="text" className="form-control" defaultValue={price.desc} onChange={this.setDesc(this, i).bind(this, i)}/>
        </td>
        <td >
          <input type="text" className="form-control" defaultValue={price.price} onChange={this.setPrice(this, i).bind(this, i)}/>
        </td>
      </tr>
    );
  }

  render() {
    return (
      <div className="row">
       ...
      </div>
    );
  }
}

这就是错误...

PriceTable.jsx:21 Uncaught ReferenceError: i is not defined
    at new PriceTable (PriceTable.jsx:21)

【问题讨论】:

    标签: reactjs twitter-bootstrap-3


    【解决方案1】:

    你绑定的函数不正确

    在你的构造函数中你不需要指定参数,你只需要像this.setDesc = this.setDesc.bind(this);一样绑定它

    同样在你的 onChange 中,当你想将参数传递给你用 bind 指定它的函数时,而不是作为参数传递并再次绑定它们。

    onChange={this.setDesc.bind(this, i)}
    

    你的整个代码看起来像

    import React, {Component} from 'react'
    import 'bootstrap/dist/css/bootstrap.css';
    
    export default class PriceTable extends Component {
      constructor(props, context) {
        super(props, context);
    
        this.state = {
          pid: this.props.pid || "12345",
          name: this.props.name || "name",
          prices: this.props.prices || [
            {count: 1, desc: 'one', price: 8.25},
            {count: 6, desc: 'six', price: 7.60},
            {count: 12, desc: 'twelve', price: 6.953}
          ]
        };
    
        this.setPid = this.setPid.bind(this);
        this.setName = this.setName.bind(this);
        this.setCount = this.setCount.bind(this);
        this.setDesc = this.setDesc.bind(this);
        this.setPrice = this.setPrice.bind(this);
        this.logDebug = this.logDebug.bind(this);
        this._renderPriceRow = this._renderPriceRow.bind(this);
      }
    
      setPid(e) {
        this.setState({pid: e.target.value})
      }
    
      setName(e) {
        this.setState({name: e.target.value})
      }
    
      setCount(i, e) {
        var newPrices = this.state.prices
        newPrices[i].count = e.target.value
        this.setState({prices: newPrices})
      }
    
      setDesc(i, e) {
        var newPrices = this.state.prices
        newPrices[i].sec = e.target.value
        this.setState({prices: newPrices})
      }
    
      setPrice(i, e) {
        var newPrices = this.state.prices
        newPrices[i].price = e.target.value
        this.setState({prices: newPrices})
      }
    
      _renderPriceRow(price, i) {
        return (
          <tr key={i}>
            <td >
              <input type="text" className="form-control" defaultValue={price.count} onChange={this.setCount.bind(this, i)}/>
            </td>
            <td >
              <input type="text" className="form-control" defaultValue={price.desc} onChange={this.setDesc.bind(this, i)}/>
            </td>
            <td >
              <input type="text" className="form-control" defaultValue={price.price} onChange={this.setPrice.bind(this, i)}/>
            </td>
          </tr>
        );
      }
    
      render() {
        return (
          <div className="row">
           ...
          </div>
        );
      }
    }
    

    您也可以使用 Arrow functions 来传递参数,例如

    onChange={(e) => this.setDesc(e,  i)}
    

    【讨论】:

    • 这实际上与完全不绑定函数具有相同的效果。我收到以下错误:Uncaught TypeError: Cannot read property 'setCount' of undefined at _renderPriceRow
    • 那是因为你没有绑定 renderPriceRow 函数。检查更新
    • 你能简单解释一下为什么我也要绑定那个函数吗?是因为函数超出了实际类的范围吗?这似乎是一个奇怪的样板代码。为什么不像之前的 ES5 那样绑定?
    • 您还需要绑定该函数,因为它使用this 作为调用setCount 函数的引用,并且函数中的this 指的是函数本身的上下文,如果您不这样做的话不要绑定它。很像绑定其他使用 setState 的函数
    【解决方案2】:

    像这样使用onChange 方法:

    onChange={this.setCount.bind(this, i)}
    onChange={this.setDesc.bind(this, i)}
    onChange={this.setPrice.bind(this, i)}
    

    constructor中删除这些行:

    this.setCount = this.setCount.bind(this, i);
    this.setDesc = this.setDesc.bind(this, i);
    this.setPrice = this.setPrice.bind(this, i);
    

    我们可以在constructor 中使用bind function,其中不需要额外的参数,例如您的这些functions

    this.setPid = this.setPid.bind(this);
    this.setName = this.setName.bind(this);
    this.logDebug = this.logDebug.bind(this);
    

    但是,如果在任何function 中你想传递任何额外的参数,那么你需要使用arrow functionbind,通过function 使用.bind(this, parameter)

    注意

    您需要在此处更改的另一件事是,您更新state 值的方式,您不应该直接改变状态变量。当您将array 分配给任何变量时,该变量将具有该array 的引用,这意味着您对该变量所做的任何更改都会影响原始array

    因此,您需要创建该变量的副本,然后对其进行更改并使用 setState 更新值。

    根据DOC

    永远不要直接改变 this.state,因为之后调用 setState() 可能 替换您所做的突变。把 this.state 当作是 不可变。

    【讨论】:

    • 好的,我会做复制的。实际上,您建议删除的行是我修复先前错误的天真方法:Uncaught TypeError: Cannot read property 'setCount' of undefined at _renderPriceRow
    • 不,不是这样,无论我建议什么都能正常工作,我确信,将提供一个工作代码:)
    • 因为你没有绑定_renderPriceRow函数。
    • 在构造函数中写入这一行:this._renderPriceRow = this._renderPriceRow.bind(this);
    猜你喜欢
    • 2018-12-05
    • 2012-08-30
    • 1970-01-01
    • 2016-12-28
    • 2021-09-07
    • 2021-05-30
    相关资源
    最近更新 更多