【问题标题】:React passing parameter with arrow function in child component在子组件中用箭头函数反应传递参数
【发布时间】:2017-01-06 16:41:09
【问题描述】:

我有这些父子组件,我想通过点击功能来选择子组件中的一个项目。然而,似乎子组件中的函数会自动调用,而不是等到用户单击该元素。为了更清楚,这里是我的父子组件

export class ParentView extends Component {
  state = {
    selectedItem: {}
  }

  handleClick = (item) => {
    alert('you click me');
    this.setState({selectedItem: item});
  } 

  render() {
    let item = { name: 'Item-1' };
    return (
      <div>
        <ChildItem item={item} handleClick={this.handleClick} />
      </div>
    );
  }
}

export class ChildItem extends Component {
  render() {
    const {item, handleClick} = this.props;
    return (
      <div>
        <a  onClick={handleClick(item)} />
      </div>
    );
  }
}

这些是我的组件使用箭头函数将handleClick 传递给子组件,但警报总是在第一次渲染时被调用,而不会被用户触发。有什么建议吗?

【问题讨论】:

    标签: reactjs ecmascript-6 ecmascript-2016


    【解决方案1】:

    您应该将函数本身传递给onClick,而不是传递函数调用的结果。

    如果您想使用参数调用它,您可以选择:

    • 将其与itemhandleClick.bind(this, item) 绑定。 bind 创建一个新函数将有一个预定义的第一个参数 - item
    • 传递新的箭头函数,如() =&gt; handleClick(item)

    以下示例:

    export class ChildItem extends Component {
      render() {
        const { item, handleClick } = this.props;
    
        return (
          <div>
            <a onClick={() => handleClick(item)} />
          </div>
        )
      }
    }
    

    在您的代码中,您在onClick 声明中调用了一个函数,因此handleClick 执行的结果将传递给onClick,这很可能不是您想要实现的。

    &lt;a onClick={handleClick(item)} /&gt;

    更新:

    正如@dhilt 所写,这种方法有一个缺点。由于每次调用ChildItemrender 方法时,新创建的箭头函数和.bind 也会创建新函数,因此与@987654337 之前的“缓存”结果相比,react 将威胁生成的react 元素为不同的@方法,这意味着它将来可能会导致一些性能问题,对于eslint,甚至有一个关于这个问题的规则,但你不应该因为两点而仅仅遵循这个规则。

    1) performance problems 应该被测量。我们不禁止使用Array.prototype.forEach 来支持常规的for,因为for 相同或“更快”。

    2) 将点击处理程序定义为类属性会导致组件实例的初始化步骤增加。 Re-render 在 react 中快速高效,因此有时初始渲染更为重要。

    只使用对您更好的东西,并且可能会阅读此类文章https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578

    【讨论】:

    • 谢谢,我用onClick={() =&gt; handleClick(item)}解决了
    • 我在这里没有得到的是项目如何传递给 handleClick 因为箭头函数的参数是空的。那是如何工作的?如果我有 onClick = {this.handleClick} 和一个函数:handleClick = element => {//stuff} element 是如何传入的?
    • @Accribus 元素本身(我假设您指的是反应元素)不会为onClick = {this.handleClick} 传递,而是会传递事件。 onClick={ () =&gt; handleClick(item) }这里可以手动传递item
    • @uladzimir 我认为 Accribus 的意思是问我们如何在箭头函数的定义中使用 item,而不是作为参数传递?据我了解,这里的项目正在使用词法范围来解决。也就是说,箭头函数定义中的item会被解析为render方法中声明的item,因为箭头函数是在render方法的词法环境中定义的。我说的对吗?
    【解决方案2】:

    接受的答案会影响性能:即使数据没有更改,ChildItem 组件也会重新渲染,因为每次渲染都会分配一个新函数(这是因为 .bind;与箭头函数相同)。在这种特殊情况下,很容易通过从新公共类字段的props 获取处理程序及其参数来避免此类问题:

    export class ChildItem extends Component {
    
      onClick = () => {
        this.props.handleClick(this.props.item);
      }
    
      render() {
        return (
          <div>
            <a  onClick={this.onClick} />
          </div>
        );
      }
    }
    

    ParentView 保持不变。

    【讨论】:

    • 在这种情况下,如果我们使用类或函数组件有什么区别吗?
    • @Leff 当然。如果是功能组件,您将如何定义 onClick?这将等同于在类组件的渲染上定义它,这是我们想要避免的。
    【解决方案3】:

    ES6方式:

    使用箭头函数 =>

    onClick={() => handleClick(item)}
    

    (@havenchyk 的回答是 ES5 方式)。

    【讨论】:

      猜你喜欢
      • 2015-01-25
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      • 1970-01-01
      • 1970-01-01
      • 2021-07-27
      • 2018-12-13
      • 1970-01-01
      相关资源
      最近更新 更多