When creating a React class, which is preferable?
export default class Foo extends React.Component {
constructor (props) {
super(props)
this.doSomething = this.doSomething.bind(this)
}
doSomething () { ... }
}
or
export default class Foo extends React.Component {
doSomething = () => { ... }
}
A coworker of mine thinks that the latter causes memory problems because babel transpiles the code to capture this
inside the closure, and that reference will cause the instance to not be cleaned by GC.
any thoughts about this?
In ReactJs, when we are working with class-based components and want to access this inside a class method. This will need to bind it. Binding this allows it to access the state and setstate inside the class. To avoid the need for binding we have something introduced in ES6 as arrow functions.
Learn more at the React docs. If you use arrow functions within render , each call to render will create new function objects. If you then pass these functions to child elements via props , optimizations based on PureComponent or shouldComponentUpdate will fail (as the arrow function props will change on every render).
Arrow functions cannot be used as constructors.
The takeaway: Function expressions are best for object methods. Arrow functions are best for callbacks or methods like map, reduce, or forEach.
The public class field syntax (so doSomething = () => {...}
) is not yet part of ECMAScript but it is doing well and I am pretty confident that it will get there.
So using this syntax forces you to transpile, but it brings advantages:
this
bindingFor me, this is a clear win. In most cases, you don't even need a constructor(props)
, saving you from that boilerplate super
call.
If the Babel implementation would cause memory leaks, you can be sure those would have been found and fixed quickly. You are more likely to create leaks yourself by having to write more code.
Binding in the render function causes new functions to be created on every render, this means the diffing algoritm thinks there are changes. When you bind in the constructor this does not happen.
Here you can see the compiled difference for binding with arrow and binding in the constructor: https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-2&experimental=true&loose=false&spec=false&code=class%20x%20extends%20React.Component%20%7B%0A%20%20constructor%20(props)%20%7B%0A%20%20%20%20super(props)%3B%0A%20%20%20%20%0A%20%20%20%20this.onChange%20%3D%20this.onChange.bind(this)%3B%0A%20%20%7D%0A%20%20%0A%20%20onChange%20()%20%7B%20console.log(%27change%20x%27)%3B%20%7D%0A%7D%0A%0Aclass%20y%20extends%20React.Component%20%7B%0A%20%20onChange%20%3D%20()%20%3D%3E%20%7B%20console.log(%27change%20y%27)%3B%20%7D%0A%7D
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With