Reputation: 5
I am currently very confused about when should we use arrow function and when we should not. I did the search about this but still I'm not clear. For example, I create a button to count clicks, the code is like below:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {counter: 0};
}
buttonPressedIncrease = () => {
this.setState((prevState) => {
return {counter: prevState.counter + 1}
});
}
render() {
return (
<div>
<div>Counter: {this.state.counter}</div>
<button onClick={this.buttonPressedIncrease}>+</button>
</div>
);
}
}
When I use arrow function on the button like this: onClick={() => this.buttonPressedIncrease}, the function does not work like I use in the code above.
Anyone can explain for me this problem? When will arrow function work and when will it not?
Many thanks in advance.
Upvotes: 0
Views: 177
Reputation: 74695
You have already defined buttonPressedIncrease
as a "fat-arrow" function:
buttonPressedIncrease = () => {
This means that if you write () => this.buttonPressedIncrease
, you are passing an anonymous function that returns the function. onClick
wants a function that does something, not a function that returns another function.
Since you are using a fat arrow when you define the function, this
is already bound correctly, so you should just pass the name of the function:
onClick={this.buttonPressedIncrease}
Sometimes in JSX you see onClick={() => someFunction()}
(note that someFunction()
is being called, unlike in your example), which may be the source of your confusion. This is another way to keep the right this
in scope but comes at the cost of creating a new function every time your render
method is called. For this reason, the above approach is preferred.
Upvotes: 2
Reputation: 321
Please note that arrow function is just a different syntax of the traditional javascript function(pseudo code):
function funcName(arg1,arg2) {
return returned_exp/value
}
Arrow representation
const funcName = (arg1,arg2) => returned_exp/value
Now, note that the returned expression can be a function here.
So in your code
<button onClick={this.onClickHandler}></button>
you just pass a function that needs to be executed onClick. Where as in below code
<button onClick={() => this.onClickHandler()}></button>
you pass a function which, when executed executes the function this.onClickHandler ( a set of open and closed parenthesis calls a function). So generally we use the latter approach when we need to pass some data/object/function to the onClickHandler as arguments like so:
<button onClick={() => this.onClickHandler(this.props.requiredStuff)}></button>
Hope this helps !
Upvotes: 0
Reputation: 59541
In short, event listeners such as onClick
expect to be given a reference to the function you want to invoke.
With this in mind:
onClick={this.buttonPressedIncrease}
is correct because this.buttonPressedIncrease
is a reference to a function and it is the one you want to run.
However,
onClick={() => this.buttonPressedIncrease}
is incorrect because while () => this.buttonPressedIncrease
is a function reference, it is not the function you want to execute. You don't want to execute the anonymous function () => this.buttonPressedIncrease
, you want to execute this.buttonPressedIncrease
. Remember that functions are only invoked with ()
. Ignoring the parenthesis only returns their reference. That's why this won't work - the anonymous function doesn't invoke the wanted function.
Though, if you want, you could do:
onClick={() => this.buttonPressedIncrease()}
because the anonymous function will invoke the wanted function. Though I'd stick to the former solution.
Upvotes: 1