I would like to know if, in React.js, there is a performance difference between declaring an anonymous function, a named function, or a method within a component.
Concretely, is one of the following more performant than the others?
class MyComponent extends React.Component {
render() {
return (
<input
type="text"
value={foo}
onChange={(e) => {
this.setState({ foo: e.target.value });
}}
/>
);
}
}
class MyComponent extends React.Component {
...
render() {
function handleChange(e) {
this.setState({ foo: e.target.value });
}
return (
<input
type="text"
value={foo}
onChange={handleChange}
/>
);
}
}
class MyComponent extends React.Component {
...
handleChange(e) {
this.setState({ foo: e.target.value });
}
render() {
return (
<input
type="text"
value={foo}
onChange={this.handleChange}
/>
);
}
}
Yes there most certainly is, The third version of you're code is the correct way of referencing a function within the Render block of a react component.
Why?
Generally nesting functions is considered an anti-pattern for methods that will be called more than once or twice; This is due primarily to the fact the javascript engine sees functions as any other value and must create & then subsequently destroy it after the parent call has completed.
If you need to be able to access this
from within handleChange()
you need to bind the method to the context of the component. The following are the methods that would not result in any negative performance impact.
Vanilla ES6 via constructor:
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
this.setState({ foo: e.target.value });
}
render() {
return (
<input
type="text"
value={foo}
onChange={this.handleChange}
/>
)
}
}
Arrow function in Class Property (requires babel w/ transform-class-properties):
class MyComponent extends React.Component {
handleChange = (e) => {
this.setState({ foo: e.target.value });
}
render() {
return (
<input
type="text"
value={foo}
onChange={this.handleChange}
/>
)
}
}
Decorated Class method (requires babel w/ transform-decorators-legacy and core-decorators):
import { autobind } from 'core-decorators'
class MyComponent extends React.Component {
@autobind
handleChange(e) {
this.setState({ foo: e.target.value });
}
render() {
return (
<input
type="text"
value={foo}
onChange={this.handleChange}
/>
)
}
}
Hope this helps!
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