最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Avoiding inline functions in React: How to bind functions with arguments? - Stack Overflow

programmeradmin0浏览0评论

I'm trying to follow the no-bind rule for React using the pattern that they have recommended with ES6 classes:

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
  }
}

However, when I need to pass arguments in to _onClick, what needs to change?

I've tried something like:

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);
  }
}

However, this does not work. What needs to be altered?

I'm trying to follow the no-bind rule for React using the pattern that they have recommended with ES6 classes:

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
  }
}

However, when I need to pass arguments in to _onClick, what needs to change?

I've tried something like:

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);
  }
}

However, this does not work. What needs to be altered?

Share Improve this question edited Feb 14, 2017 at 17:09 TheRealFakeNews asked Feb 14, 2017 at 16:47 TheRealFakeNewsTheRealFakeNews 8,15323 gold badges77 silver badges130 bronze badges 1
  • I do not know React, but my guess would be that if the arguments are already bound then the handler should remain unchanged: <div onClick={this._onClick}> – Matteo Tassinari Commented Feb 14, 2017 at 16:50
Add a comment  | 

4 Answers 4

Reset to default 8

The call to bind in the constructor should only pass this as a single argument.

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

Here you are overwriting the property this._onClick with a new one that has the correct this bound. If your function takes two arguments, then you should pass those as normal at call time.

Passing additional arguments to bind means that the function returned already has those arguments supplied - in your attempt the _onClick function will always have its first two arguments undefined, as a and b have no value in the constructor.

Now that you have bound this to your function, you can access this.props from within there, rather than having to pass arguments:

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);
  }
}

You should use partial application. Basically you initialise your onClick function with the parameters you want, and the onClick function will return a new function to be called when the div is clicked.

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: this only applies if your parameters a and b are not part of your this.props, if they are then you should just do as Tom Fenech said.

To answer your question there is nothing special you have to do in order to pass arguments to your this._onClick function.

the proper revised code will be:

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);
  }
}

Secondly, the way you are calling this._onClick is not the right way to invoke a function on click.

Right now what is happening that on each render process your function is getting called because you didn't pass the function as an argument rather you invoked that function and assigned its returned value to the onClick prop.

you have to do this like:

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

By Invoking your function this way you ensure the this._onClick will get called when click event occurs.

Another method is to use Babel stage 1 autobind and skip the constructor.

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>
    );
  }
}

发布评论

评论列表(0)

  1. 暂无评论