Click here to Skip to main content
15,881,588 members
Articles / Web Development / React

Don't Use Bind When Passing Props

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
5 Jul 2016CPOL3 min read 7.1K  
Do not use bind when passing props

Don't call .bind when passing props

There are many situations when writing React where you’ll want to pass a function to a prop. Usually, it’s to pass a callback down to a child component so that the child can notify the parent of some event.

It’s important to keep in mind the binding of the function – what its this object will point to when it’s called.

There are a few ways to make sure the binding is correct, some better than others. This post will go over the options.

Way #1: Autobinding (good, only with React.createClass)

If you’re using React.createClass, the member functions in your component are automatically bound to the component instance. You can freely pass them around without calling bind, and you’re always passing the same exact same function so there’s no performance penalty.

JavaScript
var Button = React.createClass({
  handleClick: function() {
    console.log('clickity');
  },
  render: function() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
});

Way #2: Calling .bind Within render (bad, ES6)

When using ES6 classes, React does not automatically bind the member functions inside the component.

Binding at the last second like this is one way to make it work correctly, but it will hurt performance because a new function is being created every time it re-renders (which could be pretty often).

JavaScript
class Button extends React.Component {
  handleClick() {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={this.handleClick.bind(this)}/>
    );
  }
}

Here’s another variant that is just as bad, creating a function every time render is called:

JavaScript
class Button extends React.Component {
  handleClick() {
    console.log('clickity');
  }

  render() {
    var handleClick = this.handleClick.bind(this);
    return (
      <button onClick={handleClick}/>
    );
  }
}

Way #3: Arrow Function in render (bad, ES6)

Similar to the above example, except this one uses an arrow function instead of calling bind. It looks nicer, but it still creates a function every time render is called! No good.

JavaScript
class Button extends React.Component {
  handleClick() {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={() => this.handleClick()}/>
    );
  }
}

Way #4: Class Instance Field With an Arrow Function (good, ES8+)

This method works by setting handleClick to an arrow function one time when the component is created. Inside render and in other functions, this.handleClick can be passed along without fear because the arrow function preserves the this binding.

This one is labelled “ES8+” because it’s not technically part of ES6 or ES7 (aka ES2016). ES2016 has been finalized and only includes Array.prototype.includes and the exponentiation operator, so if and when this makes it into the spec, it’ll likely be ES2017 (ES8) or beyond.

Even though this is supported by Babel, there’s a (small) risk that this feature could be taken out of the spec and require some refactoring, but a lot of people are using it so it seems likely that it’ll stay put.

JavaScript
class Button extends React.Component {
  // Use an arrow function here:
  handleClick = () => {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
}

Way #5: Binding in the Constructor (good, ES6)

You can set up the bindings once in the constructor, and then use them forevermore! Just don’t forget to call super.

JavaScript
class Button extends React.Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
}

Way #6: Using Decorators (good, ES8+)

There’s a nice library called autobind-decorator which makes it possible to do this:

JavaScript
import autobind from 'autobind-decorator';

class Button extends React.Component {
  @autobind
  handleClick() {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
}

The @autobind decorator binds the handleClick method and you’re all set. You can even use it on the entire class, if you’re lazy:

JavaScript
import autobind from 'autobind-decorator';

@autobind
class Button extends React.Component {
  handleClick() {
    console.log('clickity');
  }

  handleOtherStuff() {
    console.log('also bound');
  }

  render() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
}

Once again, ES2016/ES7 doesn’t include this feature so you’re accepting a bit of risk by using it in your code, even though Babel does support it.

Wrap Up

That about covers the ways to bind the functions you’re passing to props. Know of any other ways? Got a favorite one? Let us know in the comments.

Don't Use Bind When Passing Props was originally published by Dave Ceddia at Angularity on July 05, 2016.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Dave is a Software Engineer in the Boston area and writes about AngularJS and other JavaScript things over at daveceddia.com

Comments and Discussions

 
-- There are no messages in this forum --