9

With constructors in es6, we are advised to bind functions early, e.g.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this); // bound early
  }

  handleClick() {
    // do stuff
  }
  ...
}

In ES5, we could typically call something like this.handleClick.bind(this, "foo") if we wanted to preserve context AND send an extra argument. What is the best pattern for this with the new class syntax in ES6 React?

For instance, if my class looked like the code below, how would I best access the "foo" and "bar" values? (I know the answer is not bind but this is how I could best illustrate the problem).

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this); // bound early
  }

  handleClick(event, value) {
    // do stuff with value ("foo" or "baz")
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick.bind("foo")} /> // incorrect code
        <button onClick={this.handleClick.bind("bar")} /> // incorrect code
      </div>
    )
  }
}
1
  • The first argument to .bind is always the this value. Therefore you would want this.handleClick.bind(null, "foo"). Since the function was already bound in the constructor, any value you pass as first argument is ignored. Commented Mar 2, 2016 at 5:22

2 Answers 2

16

Think that:

onClick={this.handleClick.bind(this)}

Is the same as:

onClick={e => this.handleClick(e)}

So you can do:

    <button onClick={e => this.handleClick(e, 'foo')} />
    <button onClick={e => this.handleClick(e, 'baz')} />

In the end it is all just JavaScript.

Sign up to request clarification or add additional context in comments.

2 Comments

What exactly does "incorrect code" mean in this answer?
This way will create a new function in each render, which slows down the app since React has to unregiste the old handler and register the new handler.
6

In ES5, we could typically call something like this.handleClick.bind(this, "foo") if we wanted to preserve context AND send an extra argument.

You can do exactly the same in ES6 as well. It's not like bind was removed from the language :-)

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handleFooClick = this.handleClick.bind(this, "foo"); // bind early
  }

  handleClick(value, event) {
    //        ^^^^^^ notice the bound values come first
    …
  }

  render() {
    return (
      <div>
        <button onClick={this.handleFooClick} /> // use early-bound
        <button onClick={this.handleClick.bind(this, "bar")} /> // bind late
        <button onClick={event => this.handleClick("foobar", event)} /> // arrow function
      </div>
    )
  }
}

4 Comments

@elclanrs: Oops, that messed up arguments order in the bind call was a typo. this.handleClick.bind(this, "bar") should be equivalent to (...args) => this.handleClick("bar", ...args)
This answer saved my bacon in a vanilla ES6/babel with classes scenario, thanks.
Note that this will crate a new function each time the component is rendered, slowing down the app a bit.
@JF Then use the early-bound alternative I've shown

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.