将多个参数传递给 React 中的事件处理程序

Posted

技术标签:

【中文标题】将多个参数传递给 React 中的事件处理程序【英文标题】:Pass multiple parameters to event handlers in 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)

【问题讨论】:

【参考方案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);

以上是关于将多个参数传递给 React 中的事件处理程序的主要内容,如果未能解决你的问题,请参考以下文章

如何将自定义参数传递给事件处理程序

如何将事件和其他参数传递给单击处理程序

如何在 React-Recompose 应用程序中将事件处理程序传递给 React-node

[react] 在React中怎么将参数传递给事件?

Vue3 - 将多个事件侦听器及其处理程序传递给子组件

将参数传递给更高级别的事件处理程序