What is the difference between these function calling styles?
onPress = { () => { this.myFunctions() } }
And
onPress = { this.myFunctions() }
onPress={() =>{this.myFunctions()}}
You are passing an anonymous function which after onPress was invoked would call this.myFunctions()
onPress={this.myFunctions()}
You are passing into onPress the return value of this.myFunctions which means this gets executed everytime render is invoked by the component.
Both of the above ways of passing function into a React component are not advisable performance-wise. Using the above methods causes the function with the onPress to rerender everytime the parent renders because as it does a shallow comparison of previous anonymous function declaration it will result in two function not being equal as it is compared by reference.
It is advised to use below:
onPress={this.myFunctions}
where you are passing the reference of the function myFunctions. And whenever the parent rerenders, once the component has checked if new myFunctions is the same with previous render, it will return as true and will not render again the child.
You can use both
onPress={() =>{this.myFunctions()}}
//and
onPress={this.myFunctions} // without ()
If you want to pass arguments, you should use first one.
onPress={(e) =>{this.myFunctions(id, e)}}
There is a huge difference here.
onPress={this.myFunctions()}
The usage above means to evaluate the result of myFunctions and use the result in on press. This would only make sense if myFunctions() returned another function.
onPress={() =>{this.myFunctions()}}
The above means when onPress is triggered, then myFunctions is ran.
No, there's no real difference as long as it's just one function - although without the () (parentheses) in your second approach:
onPress={this.myFunctions}
If you want arguments:
onPress={e => this.myFunctions(e)}
Related
In a tutorial related to React, which I am watching on YouTube:
https://www.youtube.com/watch?v=h3KeJRKYpj8
there was a piece of code that had the following (minute 13:40 in the video)
const setCounterWithValue = (value) => {
setCounter(value)
}
this function gets called from a button component in the following code:
<button onClick={() => setCounterWithValue(counter -1)}
The video tutorial suggested a way to shorten this function call and make it simpler.
So what he did was modifying the code to be as follows (minute 14:30 in the video):
const setCounterWithValue = value => () => {
setCounter(value)
}
which meant the button component became as follows:
<button onClick={setCounterWithValue(counter -1)}
So my problem here is that I was expecting the setCounterWithValue to be structured as the following:
const setCounterWithValue = () => (value) => {
setCounter(value)
}
so empty () then pass value which triggers the setCounter.
I would like to have some deep explanation and some resources (like articles and videos) that explain this in further details.
I disagree that its simpler... What they are doing is called currying. Its a shorthand way to create a function that returns a function. So a longhand form would look like this:
const setCounterWithValue = (value) => {
return function () {
setCounter(value)
}
}
Its probably easier to understand why the parameters go where they do when written in this form. When you call it inline you're calling the outer function <button onClick={setCounterWithValue(counter -1)} />. It then returns the a function that should be called when the button is clicked.
What they're doing there is called currying. In other words, it's a function that returns another function. Instead of firing it outright, they're taking the value of the first function's argument and utilizing it in the second function that is fired from the the click event. In this particular case I don't see it being any simpler as you're getting the same exact outcome but in this case your original function is just fired in the second function body. Nevertheless, more info on currying can be found here.
Calling the "simpler" function with setCounterWithValue(counter - 1) will return a function that, when executed, will pass through the counter value provided. The concept for this is called currying through the use of a closure. The function you "expected" wouldn't make much sense because you'd be calling it with a value, but that value never gets captured, so the function it returns is expecting a value parameter, which is not passed, it gets lost.
Here's the two examples:
Example 1:
const setCounterWithValue = value => () => {
setCounter(value)
}
When called with setCounterWithValue(42), it will return the following:
() => { setCounter(42) }
Example 2:
As opposed to what you said you expected, which would end up like the following:
const setCounterWithValue = () => (value) => {
setCounter(value)
}
Called with setCounterWithValue(42) would return the following:
(value) => { setCounter(value) }
Notice how the function being returned still expects a value to be provided. This is the difference between the two examples and why Example 1 would work, while this one wouldn't.
This is an example of currying, which you can use as an introduction to Higher Order Functions which are very common in the React ecosystem.
To break down what happens in this case and why your assumption on how the function should look is wrong, you first have to understand what JavaScript closures are.
Let's say we have this piece of code:
function foo() {
var bar = 5;
return function baz() {
console.log(bar);
}
}
foo(); // Returns a function. Nothing happens
foo()(); // The returned function is executed. Prints 5
Here we take advantage of a closure that is created on line 3. The function baz that we return from foo captures the context of its definition site (definition site = where the function is defined = in this case the foo function). So baz can be called from anywhere and still have access to the place in memory that bar points to.
The first invocation does nothing since the returned function is not called.
The second invocation calls the returned function therefore printing the number 5 to the console.
In order to understand your example snippet you can be more explicit in the function definition:
This:
const setCounterWithValue = value => () => {
setCounter(value)
}
can be rewritten like this:
function setCounterWithValue(value) {
return function() {
setCounter(value)
}
}
The instructor in the video just takes advantage of the implicit return feature of arrow functions
The code snippet just above will have the same result when used with your code. Hopefully, written like this, it makes more sense to you why there is no need for the anonymous function to have a value argument. It can access it via a closure.
As to why currying and high order functions are preferred by some JavaScript developers, the answer is way too long and opinionated, so I suggest you study the subject a bit more. A very interesting article can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
A bit harder to read but with a bunch of useful theory: https://eloquentjavascript.net/05_higher_order.html
It is easier to understand using function declaration instead of arrow functions. The tutorial suggests you refactor the function into a function factory:
function setCounterWithValue (value) {
return function () {
setCounter(value);
}
}
This means that calling the function above will return a function that requires no arguments:
let f = setCounterWithValue(1);
f(); // this sets counter to 1
Your suggested function instead returns a function that requires an argument:
function setCounterWithValue () {
return function (value) {
setCounter(value);
}
}
This means to set the value you will have to pass an argument:
let f = setCounterWithValue();
f(1); // set value to 1
The problem the refactor is trying to solve is that onclick functions are always called with an event object as the argument. When the button is clicked, the browser will call your function as:
setCounterWithValue(event);
You have no control over this. It is impossible to force the browser to call it any other way. Thus, ideally you want to pass into the onclick handler a function that ignores the event argument:
function setCounterWithValue (value) {
return function () {
setCounter(value);
}
}
let f = setCounterWithValue(counter -1); // this returns a function
// that ignores arguments
return <button onClick={f} />
most people would avoid using a temporary variable so:
<button onClick={setCounterWithValue(counter -1)} />
On the other hand, if you use your suggestion you would need to do:
{/* wrap in an anonymous function to ignore the event */}
<button onClick={() => setCounterWithValue(counter -1)} />
'm learning native react and learning more about javascript, so I still do not understand many things about its behavior. I have created a button component, using TouchableOpacity, and its props onPress.
For it to work, I must send the function I want to execute as a props, but here I have fallen due to my little experience.
I am sending a console.log that is activated when I press the button. So I passed the console.log directly in the props that I defined, but it did not work when I clicked on the button, but, it was executed when the code is initialized. On the other hand, when I have passed an arrow function that contains the console.log, it has been executed at the moment of clicking the button.
to make it clearer I'll show my code:
this is my button component:
const Button = ({ onUserPress, children, color }) => {
const state = {
};
return (
<TouchableOpacity onPress={ onUserPress } style={styles.buttonStyle} >
<Text style={styles.textStyle}>
{children}
</Text>
</TouchableOpacity>
);
};
and i call them like this:
<Button onUserPress={ console.log("hello") }>Something</Button>
This is executed at the time of initializing my application, and nothing is happened when the button is pressed.
on the other hand, when i use the same component, but i pass the console.log in arrow function, like this:
<Button onUserPress={ ()=>{console.log("hello")} }>Something</Button>
this execute the console log only when i press the button component.
Could someone explain to me why the behavior is different? The world of functional programming is totally new to me and these things seem strange to me. According to what I understand, both are functions, so for me they do not make a difference (obviously, from my ignorant point of view). What is the difference that makes the behavior different?
You aren't comparing a "normal function" with an arrow function.
The content between { and } is an expression which is evaluated and the result is assigned to the prop.
Thus you are calling console.log("hello"), taking the return value and assigning that as a function to onUserPress (this makes no sense as the return value of console.log is not a function).
Not a function:
console.log("hello");
If you don't want use arrow function you need to pass a regular function: onUserPress={ function(){console.log("hello")}.
Also, you can pass onUserPress={console.log}, in this case, console.log will receive an event object as a parameter.
Difference in function(){console.log("hello") and () => console.log("hello") that in second case "this" will be pointed to your component
1-> <Button onUserPress={ console.log("hello") }>Something</Button>
2-> <Button onUserPress={ () => console.log("hello") }>Something</Button>
in first : you're calling the console.log("hello") ,
where as in 2nd you're returning console.log("hello")
so its similar to
const functionCall = ()=>{
do something...
}
const x = document.getElementById("root")
x.addEventListener("click",functionCall()) <--- WRONG!!!
in the above case it will CALL the function,even before you press the
input/button which is "called" inside the 2nd parameter.
Rather
x.addEventListener("click",functionCall) <---- Correct it executes
the function when you click the button/input
I have seen a lot of reactjs places where a function is called like below
onChange = {this.fileSelected}
whereas I have seen its usage like below as well
onClick={() => this.clearDisplay()}
I want to ask if they both mean the same or is there any difference and what to use when.
If you use First:
onChange = {this.fileSelected}
It will only execute when onChange is called. If you want to bind this function then you have to declare it in the component class constructor like this:
constructor(props) {
super(props);
this.state = {
// your state
};
this.clearDisplay = this.clearDisplay.bind(this);
}
The Second one:
onClick={() => this.clearDisplay()}
This defines an anonymous function but, does not call it. Only when onClick is fired is it called. However, in some cases using an anonymous function can cause performance issues. That anonymous function will be defined on every render - and if you have a component that is re-rendering very often it can hurt the performance of your application. If you are sure that the component will not be rendered often, an anonymous function should be fine for convenience.
onChange={this.fileSelected}
Is preferable because it is able to not cause unnecessary re-renders.
onClick={() => this.clearDisplay()}
When you pass an anonymous function like this it will actually be called on all instances of the class instead of the one that the event was triggered on.
From a high level in may seem like they have the same behavior but if you were to use the second method consistently through a large codebase the performance of your application would suffer.
This article goes more in depth on the issue:
https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36
onChange = {this.fileSelected}
This will direct bind fileSelected function to onChange method. so when onChange method called it will call fileSelected function.
while
onClick={() => this.clearDisplay()}
This will call onClick function in which you are calling clearDisplay function. so when you onClick method called, first anonymous called in which clearDisplay function called. So basically in this method two functions called. in this methos you can do additional calls or other things
e.g.
onClick={() => {
console.log("this function called")
this.clearDisplay();
}
I am looking at this code: https://reactjs.org/docs/state-and-lifecycle.html
I do not understand why I need to use () => this.tick() instead of just this.tick(). The prior calls a function that uses this.tick(), yet when I change () => this.tick() to this.tick(), the code stops working. this.tick() is no longer being called even though it itself is a function. () => this.tick() seems to be just an unnecessary step and yet it is necessary.
I think I am misunderstanding functions as objects.
Thank you
If you pass () => this.tick() then you are passing a function.
If you pass this.tick() then you are passing the value returned by the function.
setInterval(func, delay[, param1, param2, ...]) expects a function as first parameter.
() => this.tick() is a function that when executed will call this.tick() with the appropriate context. If you didn't want to use arrow syntax, you would need to bind the this context similar to this.tick.bind(this);
The arrow function used there is needed to bind the this context, so that it can use this in it's own function.
If you would have only setTimeout( this.tick, 1000 ), it would rightfully call the function on the class, however, that function wouldn't have a this scope...
...unless you bind the this scope in the constructor, or as part of the setTimeout call itself
To do it in the constructor you would have something like
class Clock extends Component {
constructor() {
super();
this.tick = this.tick.bind(this);
}
// other functions
tick() {
this.setState(/*.. state content ..*/):
}
}
another option would be the
setTimeout( this.tick.bind( this ), 1000 );
but that would do the same as what the arrow function is doing for you anyhow, so why not use the arrow function instead.
Another option would be the experimental class properties where you would still have an arrow function, but as this is not the most optimal solution when it comes to testing, I will not directly discuss that one
Firstly, setInterval takes a function as a parameter. Hence unless this.tick returns a function, passing this.tick() to setInterval is incorrect.
setInterval defers the callback method in the event loop. And hence at the time of its execution, the current reference to this will have been lost, as its scope is within its parent function which would have completed its execution. So this would be pointing to window or undefined ins strict mode.
To make it work, you need to preserve the reference, for which we create a closure by creating a new function () => this.tick. Now the reference will be preserved even after parent funtion completes its execution.
You need to give the function a callback to be invoked. A callback is a function that is to be executed after another function has finished. For example using a setTimeout is a built-in function, you give tick a callback because once setTimeout is finished you would like tick to be invoked.
Hope this helps!
I was just writing a piece of code that updates a parent component's state. This piece of code:
handlePress() {
this.props.count();
this.setState({completed: true});
};
managed to update the parent's state, where as this one
handlePress() {
this.props.count;
this.setState({completed: true});
};
did not. Therefore, what is the difference between calling functions with and without parentheses?
All you've done is referenced the function that you've passed in as a prop, you haven't attempted to execute it. What you've done is no different than if you had done this:
let count = 6;
count
That second line would be useless, as is when you simply use this.props.count instead of actually calling the function with this.props.count()