【问题标题】:Avoiding inline functions in React: How to bind functions with arguments?在 React 中避免内联函数:如何将函数与参数绑定?
【发布时间】:2017-02-14 16:47:47
【问题描述】:

我正在尝试使用他们在 ES6 类中推荐的模式来遵循 React 的 no-bind 规则:

class Foo extends React.Component {
  constructor() {
    super();
    this._onClick = this._onClick.bind(this);
  }
  render() {
    return (
      <div onClick={this._onClick}>
        Hello!
      </div>
    );
  }
  _onClick() {
    // Do whatever you like, referencing "this" as appropriate
  }
}

但是,当我需要将参数传递给 _onClick 时,需要更改什么?

我尝试过类似的方法:

import {someFunc} from 'some/path';

class Foo extends React.Component {
  constructor() {
    super();
    this._onClick = this._onClick.bind(this, a, b);
  }
  render() {
    const {
     prop1,
     prop2
    } = this.props;

    return (
      <div onClick={this._onClick(prop1, prop2}>
        Hello!
      </div>
    );
  }
  _onClick = (a, b) => {
    someFunc(a, b);
  }
}

但是,这不起作用。需要修改什么?

【问题讨论】:

  • 我不知道 React,但我猜如果参数已经绑定,那么处理程序应该保持不变:&lt;div onClick={this._onClick}&gt;

标签: javascript reactjs ecmascript-6 bind


【解决方案1】:

在构造函数中对bind 的调用应仅将this 作为单个参数传递。

this._onClick = this._onClick.bind(this);

在这里,您将使用具有正确this 绑定的新属性覆盖属性this._onClick。如果你的函数有两个参数,那么你应该在调用时像往常一样传递它们。

bind 传递附加参数意味着返回的函数已经提供了这些参数 - 在您的尝试中,_onClick 函数将始终具有其前两个参数undefined,因为ab 没有构造函数中的值。

现在您已将this 绑定到您的函数,您可以从那里访问this.props,而不必传递参数:

import {someFunc} from 'some/path';

class Foo extends React.Component {
  constructor() {
    super();
    this._onClick = this._onClick.bind(this);
  }
  render() {
    return (
      <div onClick={this._onClick}>
        Hello!
      </div>
    );
  }
  _onClick() {
    const {
     prop1,
     prop2
    } = this.props;
    someFunc(prop1, prop2);
  }
}

【讨论】:

    【解决方案2】:

    您应该使用partial application。基本上你用你想要的参数初始化你的onClick函数,当div被点击时,onClick函数会返回一个新的函数来调用。

    import {someFunc} from 'some/path';
    
    class Foo extends React.Component {
      render() {
        return (
          <div onClick={this._onClick(prop1, prop2)}>
            Hello!
          </div>
        );
      }
      _onClick = (a, b) => {
        return () => someFunc(a, b);
      }
    }
    

    PS:这仅适用于您的参数ab 不是this.props 的一部分,如果它们是,那么您应该按照Tom Fenech 所说的那样做。

    【讨论】:

    • 这个解决方案是完全错误的。它只是防止 ESLint 警告。但是在每次渲染上创建新函数的问题仍然委托给中间函数。编辑:由于这次合并(github.com/yannickcr/eslint-plugin-react/issues/1444),这个解决方案甚至不能阻止警告。
    • 在优化方面这是一个非常糟糕的解决方案! _onClick 这里每次都返回一个新函数。即使两个函数具有相同的函数定义,它们也会通过相等性测试,因为两个单独的对象永远不会相等
    【解决方案3】:

    要回答您的问题,您无需执行任何特殊操作即可将参数传递给您的 this._onClick 函数。

    正确的修改代码是:

    class Foo extends React.Component {
      constructor() {
        super();
        this._onClick = this._onClick.bind(this);
      }
      render() {
        return (
          <div onClick={() => this._onClick(1, 2)}>
            Hello!
          </div>
        );
      }
      _onClick = (a, b) => {
        console.log(a, b);
      }
    }
    

    其次,您调用this._onClick 的方式不是在click 上调用函数的正确方式。

    现在发生的情况是,在每个渲染过程中都会调用您的函数,因为您没有将函数作为参数传递,而是调用了该函数并将其返回值分配给 onClick 属性。

    你必须这样做:

    render() {
      return (
        <div onClick={() => this._onClick(prop1, prop2)}>
          Hello!
        </div>
      );
    }
    

    通过这种方式调用您的函数,您可以确保在点击事件发生时调用this._onClick

    【讨论】:

      【解决方案4】:

      另一种方法是使用 Babel stage 1 自动绑定并跳过构造函数。

      import {someFunc} from 'some/path';
      
      class Foo extends React.Component {
        _onClick = () => {
          const {
           prop1,
           prop2
          } = this.props;
          someFunc(prop1, prop2);
        }
      
        render() {
          return (
            <div onClick={this._onClick}>
              Hello!
            </div>
          );
        }
      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-25
        • 2018-08-05
        • 1970-01-01
        相关资源
        最近更新 更多