5 ms·
This would have been a good post in 2014 but it shouldn't be relevant to any JavaScript developers in 2018. Arrow functions don't have `this`, and `...` syntax
by digitaLandscape 8y ago
This would have been a good post in 2014 but it shouldn't be relevant to any JavaScript developers in 2018.
Arrow functions don't have `this`, and `...` syntax is simpler and as efficient as using `apply`. You only still need to use `function(){}` for generators and custom constructors, which are rare.
- sdegutis 8y agoVery relevant in 2018. React uses ES6 classes (inherit from React.Component) so you're very often using `this` in React. In fact it's still a major source of confusion still for many devs like me, especially when you create and pass callback functions. I've been meaning to write a blog post on this so maybe this is the motivation I needed.
- digitaLandscape 8y agoJust use arrow functions for your callbacks! This is trivial. Don't create a problem that doesn't exist.
- sdegutis 8y agoThis results in extra renders for an entire component chain, because comparing two arrow functions will always be different whereas comparing two pre-defined functions will always be the same. Hence React's recommendation to use 'bind'.
- gear54rus 8y agoWhat I don't get is why the React guys don't just call the passed functions with 'this' being the component, which seems like the most common use case. If you need to override this, you could indeed use bind (it's not overridable after that AFAIK so no logic is required from React side).
- sdegutis 8y agoThat's a good question, I never thought of that. Maybe while rendering they don't have easy access to which component is "this" due to the recursive algorithm they probably use? That's my only guess.
- acemarke 8y agoBecause it's really _not_ "the most common use case". Components often pass down callbacks through multiple levels of children. A basic example would be a Form component that renders something like: <Button onClick={this.onFirstNameChanged} /> The proper context for `this` is the Form, but the callback is used in the context of the Button. Besides, one of the main tenets of React is that "it's just JS", so normal JS rules apply. Now, the old-style `React.createClass()` method _did_ actually bind all "class methods" to the component instances so you didn't have to worry about it, but that wasn't typical JS behavior. ES6 classes don't auto-bind their methods, so neither does the `React.Component` base class. The current recommended approach is to use the Stage 3 Class Properties syntax, which allows defining class methods as arrow functions that are auto-bound to the proper class/component instance. Very long-term, the React team intends to introduce a "stateful functional component" API that doesn't have to worry about class instances, but that's going to be a while. (There are some assorted userland experiments with writing "`this`-less components" as well.)
- acemarke 8y agoNo, that's only true _if_ a child component is explicitly attempting to optimize its performance by doing shallow equality checks on its props in `shouldComponentUpdate` (or is a `PureComponent`, which does the same thing automatically). Otherwise, React's default behavior is to re-render a component tree all the way down anyway, so it doesn't matter whether a given prop has actually changed its reference or not. See this post by Ryan Florence that explains why "arrow functions in render" is not a big deal: https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578 https://cdb.reacttraining.com/react-inline-functions-and-per...
- ggregoire 8y agoWhat do you find confusing about callback functions? Maybe I can help. Here is a simple example: class Foo extends Component { state = { foo: 1 } updateState = foo => this.setState({ foo }) render() { return <FooChild foo={this.state.foo} updateState={this.updateState} /> } } Foo and FooChild will render again only if 'foo' is updated.
- sdegutis 8y agoThis is the solution I've been using, but it's not ideal. The lambda stored in updateState is recreated every time the class is instantiated, which can create problems for the GC depending on how often React creates temporary instances of Foo for its internal purposes.
- ggregoire 8y agoThat's how classes work, the lambda doesn't change anything here. The GC deals with it without problems. If an instance of Foo is not used anymore, the GC will destroy it and anything bound to it.
- sdegutis 8y agoES6 methods are defined outside the constructor so are O(1), but all class-fields are assigned inside the constructor thus O(n), so it can make a difference.
- acemarke 8y agoThat statement seems wrong, or maybe I'm having trouble interpreting the way you're phrasing things (particularly with your use of "O(1)" and "O(n)"). Standard ES6 class methods are defined on the _prototype_, so only one function reference exists per method. Binding class methods per instance, either by hand or using the Stage 3 Class Properties syntax, would result in a separate function reference per method per class instance (ie, 4 bound methods on a component class, times 5 instances of that component, would be 20 method references in memory instead of 4). So yes, binding methods technically has some perf overhead, but most apps are unlikely to be creating thousands of instances of any given component type. To me, this is not a realistic concern. (In fact, if you think about it, you're generating _lots_ of functions every time you re-render if you're calling something like `someArray.map(() => {})` - way more than you ever would just from instantiating some components.)
- aphextron 8y agoEvery time you call this within an arrow function, the transpiler is still just doing a “this = that” in your code for you.