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.
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.
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.
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 !
Related
I am React beginner. I've seen some code in a React project that I did not understand.
What is the difference between this.function and the following function call in a React event handling prop?
<button onClick={this.clickHandler}></button>
<button onClick={() => this.clickHandler()}></button>
Can anyone kindly explain to me what the difference is in the example above?
This is Traditional :-
var obj = {
count : 10,
doSomethingLater : function (){
setTimeout(function(){ // the function executes on the window scope
this.count++;
console.log(this.count);
}, 300);
}
}
obj.doSomethingLater(); // console prints "NaN", because the property "count" is not in the window scope.
And this is Arrow :-
var obj = {
count : 10,
doSomethingLater : function(){ // of course, arrow functions are not suited for methods
setTimeout( () => { // since the arrow function was created within the "obj", it assumes the object's "this"
this.count++;
console.log(this.count);
}, 300);
}
}
obj.doSomethingLater();
More information
The latter creates a useless anonymous wrapper function around this.clickHandler.
the first one creates an anonymous function around your first function.
let's turn it into vanilla javascript (a bit modified though)
<! -- equivalent to <button onClick={() => this.clickHandler()}></button> -->
<button id="btn-2">button 2 </button>
<script>
document.querySelector("#btn-2").addEventListener("click", function()
{
// the above function will be created
// executing some code
clickHandler()
})
</script>
so the function nesting is just useless as you create a function whose sole purpose is to launch another function. The best way would be to do this
<! -- equivalent to <button onClick={this.clickHandler}></button> -->
<button id="btn-1">button 1 </button>
<script>
// instead of an anonymous function we directly inject the function to be lauched.
document.querySelector("#btn-1").addEventListener("click", clickHandler)
</script>
Try to avoid function nesting as it may in some extreme case overflow your memory although it is use less. Arrow function ( => ) is a javascript ES6 feature widely used by React.
Read this:- https://reactjs.org/docs/handling-events.html
The problem with this syntax is that a different callback is created each time the LoggingButton renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem.
I am not exactly sure how to describe it but let's say I have this code <button onClick={() => exampleFunction}>Text</button> and this code <button onClick={exampleFunction}>Text</button>, so what's the difference in both examples working? I noticed that in case of onChange only second example works.
Could anyone clarify it?
In your first example you're not actually invoking exampleFunction. You're providing a function that returns exampleFunction.
This:
() => exampleFunction
is the equivalent of:
function () { // invoked by the underlying component
return exampleFunction; // returned, but never called.
}
To fix it, add the parens:
() => exampleFunction()
In the second form, you're passing exampleFunction directly, which is a function. It gets invoked by the underlying component.
I've been trying to learn the basics of React. However, I've come across a section in the tutorial that asks me to place an alert() inside of an onClick event as such:
<button className="square" onClick={() => {alert("click");}}>
{this.state.value}
</button>
I don't understand why the arrow function is required - why can't I just have the alert() on its own?
The docs state:
Forgetting () => and writing onClick={alert('click')} is a common mistake, and would fire the alert every time the component re-renders.
Which is correct - I've tried this, and it does continually call alert(). But why? Isn't it supposed to fire onClick, and not on render? What does the anonymous function do that stops this behaviour?
Because if you call a function, then the function runs. (And you get the return value from it)
const onClick = alert("hello");
console.log(onClick);
If you define a function (X) that calls a function (Y), then it doesn't call Y until you call X.
const onClick = () => alert("hello");
console.log(onClick);
Basically there is differences between calling (Invoking) a function alert() and Defining (Expressing) a function () => {alert()}
When the code runs, i.e when react renders the component, any function call would run that function and that's why we can use IIFE (function() { } )() to inject functions to window object at runtime.
However, handling events with inline function call (like onclick={()=>{alert()}}) is not recommended because every time that event triggered, a new instance of that function would be created and it may slow down your app,
Instead you can DEFINE a function for handling events and just call it when that specific event triggered:
// Bad
render() {
return <button onclick={() => {this.setState({btnClicked: true})}}> Click! </button>
}
// Good
render() {
const handleClick = () => {
this.setState({btnClicked: true})
}
return <button onclick={handleClick}> Click! </button>
}
Because you need a function that gets called only in the instant that the button is clicked. If you pass alert('click') then the parser will find a function call and execute it instantly when it is going over that file.
I was trying to understand how the respective function call work when we use it in React
Suppose we have two functions like this
const something = () => {
//something
}
function something1 () {
//something
}
Till now, I have seen them being called in three different ways
like
{this.something}
this.something()
(() => something)
So my primary question is how are they different? like when being called and if there is any other way to call them (not mentioned here)?
this.something will not properly call a function. this.something() is the ideal way to call it because it's the most performant! () => this.something() actually triggers a re-render every time the function is called because you're creating a new function (you're literally wrapping this.something() within an empty arrow function). That being said, both are useful in different instances. When in doubt, go with this.something().
I'm getting really annoyed by this behaviour that occurs onClick:
If I have:
<button onClick={ this.myFunc(myVal) }></button>
This fires as soon as component mounts not when button is clicked, hence I need to do the following in order to fix it:
<button onClick={ () => this.myFunc(myVal) }></button>
But I believe this is not the correct way to achieve this? Also what if I want to actually pass this.myFunc(myVal) down to another component? It would not work.
When you say
<button onClick={ this.myFunc(myVal) }></button>
You are telling React that you want the returned value from executing this.myFunc(myVal) to be assigned to the onClick handler. Instead you, probably want to give it the function with the parameter set as default:
<button onClick={ this.myFunc.bind(this, myVal) }></button>
This binds myVal as the first argument to this.myFunc and ensures that the context is also bound properly as well. Keep in mind that this causes the event parameter to be passed in as the second parameter to the function.
you are calling the function while doing like below, thats why your method gets called immediately after mounting
<button onClick={ this.myFunc(myVal) }></button>
you have to just assign the function like below
<button onClick={ this.myFunc }></button>
if you want to pass variables to that method, add that variable to state and access that from ther.
The onClick attribute expects a function as a parameter.
That is why the second setup IS correct, and 1st one is not (unless myFunc returns a function)..
The following are functions:
(event) => myFunc(myVal, event) // anonymous function, which calls myFunc IF executed
myFunc.bind(this, myVal) // myFunc without parentheses, with parameters - including event - bound
The following is not a function
myFunc(myVal) // == THE RESULT of the function, so == whatever myFunc returns
In an example:
// myFunc is a function that calls another function
// returns length of whatever is passed in
myFunc(val) {
otherFunc()
return (val.length)
}
// here: myFunc is defined, but it has never executed: otherFunc was not called
let myVal = [1,2]
let callback = () => myFunc(myVal)
// here myFunc is still NOT called, neither is otherFunc
// callback is now defined as a (anonymous) function, which, whenever called
// will execute the function myFunc, by passing in the value of myVal
let a = myFunc(myVal)
// here: myFunc WILL be called, so also otherFunc
// at this point a == 2 (the length of the array myVal)
let b = callback()
// here, callback function is executed, and so also myFunc
// at this point b == 2