With the release of ES6 arrow function syntax, you now can use both regular JavaScript function and arrow function syntax when creating components. I would say that using the arrow function for React components is the right choice for most use cases.
Let’s consider the basics of both syntaxes first. Here’s how you write a normal function:
function sum(x, y){
return x+y
}
And here’s the arrow function equivalent:
const sum = (x, y) => x + y
When you have only one argument, you can skip adding the round brackets:
const add = x => x + 1
Notice how the arrow function doesn’t need a return
statement when there is only one line of code. You can even put the return on the next line:
const sum = (x, y) =>
x + y
But you still need a return
statement when you have at least 2 lines of code:
const sum = (x, y) => {
console.log("Running sum function")
return x + y
}
The arrow function is far more concise than the regular function syntax, but when you use it inside React, it has the following benefits as well:
Arrow function prevents this
keyword bug
The regular function syntax changes the context of this
keyword. When you write a class component, you can’t call on this.setState
without binding the function that calls it. The following example would throw an error when you click on the button:
class App extends React.Component {
state = {
name: "Johnson"
}
handleClick(){
this.setState({name: "Jack"})
}
render(){
return (
<div>
<p>My name is {this.state.name}</p>
<button onClick={this.handleClick}>
Change name
</button>
</div>
)
}
}
This is because the this
inside handleClick()
refers to the function context, while setState()
function is a property of the App
class. To solve the error, you need to bind
the function this.handleClick
when you pass it into the onClick
prop:
<button onClick={this.handleClick.bind(this)}>
Or you can also bind it in the constructor:
class App extends React.Component {
constructor(props){
super(props)
this.state = {
name: "Johnson"
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(){
this.setState({name: "Jack"})
}
render(){
return (
<div>
<p>My name is {this.state.name}</p>
<button onClick={this.handleClick}>
Change name
</button>
</div>
)
}
}
Now here’s one of the benefits using the arrow function: it doesn’t change the context of this
keyword, so you don’t need to bind
at all:
handleClick = () => {
this.setState({name: "Jack"})
}
render(){
return (
<div>
<p>My name is {this.state.name}</p>
<button onClick={this.handleClick}>
Change name
</button>
</div>
)
}
This might seem trivial when you only have one function, but when you have more than three functions inside your component, you need to bind them all into the class component. Forgetting to bind
a function is one of the most common causes of bugs in React.
By using the arrow function, you effectively removed the bind
and this
bugs.
Using the arrow function in render
Another way to remove the need for bind
is to pass an arrow function into the onClick
prop:
handleClick(){
this.setState({name: "Jack"})
}
render(){
return (
<div>
<p>My name is {this.state.name}</p>
<button onClick={ () => this.handleClick() }>
Change name
</button>
</div>
)
}
Passing an arrow function in render will cause React to create a new function each time the component renders. But you don’t need to worry because the impact on performance is very minuscule. It’s very unlikely that your users will experience a noticeable lag just because of arrow functions in render.
But if you want to avoid removing the arrow function for performance reasons in the future, just create the function in arrow syntax and pass it to the onClick
normally.