4 ms·
You can use the fat arrow syntax to implicitly bind a function to this: handleChange = e => this.setState({ value: e.currentTarget.value })
by adregan 8y ago
You can use the fat arrow syntax to implicitly bind a function to this:
handleChange = e => this.setState({ value: e.currentTarget.value })
- purplerabbit 8y agoThe moment es6 classes showed up without automatic method binding was the moment I fell out of love with JavaScript. I can't imagine that there would EVER be a good reason not to have a method bound to the class. Now we've all been forced to learn this new property initializer syntax and add yet another babel dependency to facilitate it.
- rpeden 8y agoWouldn't that be problematic if you're binding lots of handlers, though? It seems like the fat arrow syntax here is creating a new anonymous function for every instance of the handler. And if you've got a list of tens or hundreds of items, and you want a click handler for each, you quickly get to the point where all the extra overhead matters. Like, for instance, in a React render function you could have {things.map(thing => { return <Thing onClick={e => this.handleClick(thingId) } /> })} or {things.map(thing => { return <Thing onClick={this.handleClick.bind(this, thingId)} /> })} But option #1 would be a lot less efficient if you've got lots of things, since it's creating a new closure that calls the instance method instead of just pointing at the instance method like snipper #2 does. I still see lots of people recommending #1 for this exact scenario, though. Maybe I'm just wrong, or maybe stuff like this is why I see so many SPAs consuming shocking amounts of memory. I grant that using the fat arrow is probably fine for the scenario you mentioned though, with something like a text field. I don't think I've seen many pages with so many text fields that the extra overhead would even make a difference.
- alxlu 8y agoHaving .bind inside a JSX prop also creates a new anonymous function on each render. To avoid it, you can do (sorry for bad formatting): class Thing extends React.Component { handleClick = (thingId) => { this.setState(/*stuff*/); } render() { return <div>{things.map(thing => <Thing onClick= {this.handleClick} />)}</div> } } You can also bind handleClick inside the constructor without the arrow. constructor(...args) { super(...args); this.handleClick = this._handleClick.bind(this); } _handleClick(thing) { // stuff }
- mercer 8y agoThe latter version seems to be the one I most commonly see, except _handleClick() is just handleClick() repeated. Am I correct in assuming this is considered idiomatic at this point?
- antonkm 8y agoYes, I'd say so.
- mercer 8y agoIs this better somehow? I feel like I should know this, but it's Friday night and I'm tired, but isn't the constructor fired on every instance of the component? And if so, is this a better approach for any particular reason other than clarity?
- aenigmaclamo 8y agoIt is fired on every instance of the component. However, if you create the arrow function in the render function, it'll be created for every render. Since React keeps the component instances around between renders, it can be a lot better.
- mercer 8y agoAh, that makes sense. Do you by any chance know of any articles that go further into how this works?
- RunawayGalaxy 8y agohttps://pbs.twimg.com/media/DZ-97vzW4AAbcZj.jpg:large https://pbs.twimg.com/media/DZ-97vzW4AAbcZj.jpg:large
- mercer 8y ago
- _greim_ 8y agoI don't have any benchmarks so I won't speculate which is faster, but both these options create a new function object. The fact that one is done implicitly doesn't necessarily make it faster. I suspect performance will be highly engine- and version-specific, so best to choose the more idiomatic one (which I leave as an exercise for the reader to figure out).