React Anti Patterns Part 3
Tags: react, todayilearned
Published: 2020-02-14 20:45:52

The original post lives <a href="https://www.grantwatson.app/posts/react-anti-patterns-part-3" target="_blank">here</a>

<h1>1. bind() and arrow functions in Components</h1>\n<p>You must have bound your custom functions in the constructor function before using them as props for components. If you declare components using the extends keyword, then the custom functions (such as updateValue below) lose their this bindings. So, if you want to access this.state, or this.props or this.setState then you need to re-bind them.</p>\n\n<h3>Demo</h3>\n\n<pre><code>\nclass app extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      name: ''\n    };\n    this.updateValue = this.updateValue.bind(this);\n  }\nupdateValue(evt) {\n    this.setState({\n      name: evt.target.value\n    });\n  }\nrender() {\n    return (\n      <form>\n        <input onChange={this.updateValue} value={this.state.name} />    \n      </form>\n    )\n  }\n}\n</code></pre>\n\n<h3>Problems</h3>\n<p>There are two ways to bind the custom functions to the component’s this. One way is to bind them in the constructor as done above. The other way is to bind at the time of passing as prop value —</p>\n<pre><code>\n<input onChange={this.updateValue.bind(this)} value={this.state.name} />\n</code></pre>\n\n<p>This method suffers from a problem. Since .bind() creates a new function each time it is run, this method would lead to a new function being created every time the render function executes. This has some performance implications. However, in a small app it may not be noticeable. As the app grows large, the difference will start to materialise. </p>\n\n<p>Arrow functions entails the same performance concerns that were there with bind.</p>\n\n<pre><code>\n<input onChange={ (evt) => this.setState({ name: evt.target.value }) } value={this.state.name} />\n</code></pre>\n\n<p>\nThis way of writing is definitely clearer. You can see what’s going on in the onChange prop itself. But, this also creates new anonymous function every time input renders. So it has the same performance penalty as above. Turns out, there hasn’t been any performance measurements as to how slow inline functions are. Also, most of the time, they are equally performant. Check out the article for a more in-depth discussion on this.\n</p>\n\n<h3>Solutions</h3>\n<p>\nThe best way to avoid the above performance penalty is to bind the functions in the constructor itself. This way only one extra function is created at the time of component creation, and that function is used even when render is executed again.\nIt often happens that you forget to bind your functions in the constructor, and then you get an error (Cannot find X on undefined.). Babel has a plugin that let’s you write auto-bound function using the fat-arrow syntax. The plugin is <em>Class properties transform</em>. Now you can write components like this —\n</p>\n\n<pre><code>\nclass App extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      name: ''\n    };\n// Look ma! No functions to bind!\n}\nupdateValue = (evt) => {\n    this.setState({\n      name: evt.target.value\n    });\n  }\nrender() {\n    return (\n      <form>\n        <input onChange={this.updateValue} value={this.state.name} />\n      </form>\n    )\n  }\n}\n</code></pre>