React binding function - javascript

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();
}

Related

React JS: calling event handlers

I have started working in React recently. I noticed one behaviour like when I am trying to call my event handle with the same component like this
onClick={someEventHandler} it is triggering but when I try to do the same same like this onClick={()=> someEventHandler} it doesn't work.
I noticed that when I need to pass any arguments and calling the function like onClick={()=>someEventHandler(id)} it is working fine.
can some one explain me the logic/theory behind this?
The onClick event handler needs a function to be passed to it. Whenn the event is triggered, it calls the handler function passed to it.
In the first case it works because you pass someEventHandler to onClick which is invoked when event is fired. An invocation to the function is like someEventHandler()
Now in the second case,
onClick={()=>someEventHandler}
the function passed to onClick is ()=>someEventHandler which can be elaborated further as ()=> { return someEventHandler; }
Now if you notice above you are returning a function from the onClick event handler. The returned function is now never invoked and hence you see the above behavior
It works in the last case like onClick={()=>someEventHandler(id)}, because when the event handler is invoked, it invoked someEventHandler with id too.
However you do not need to pass id to invoke it, you can simply use it like onClick={()=>someEventHandler()} and it work, provided you don't need id as a parameter in someEventHandler.
Another thing to note when you are using function like onClick={()=>someEventHandler()} instead of onClick={someEventHandler} is that your someEventHandler will not be invoked with any arguments. If you want the event to be passed as argument to someEventHandler, you need tto explicitly pass it like
onClick={(e)=>someEventHandler(e)}
onClick={someEventHandler} will trigger the handler as soon as your component gets loaded/rendered on the screen but by adding an arrow function before the handler like this - onClick={()=> someEventHandler} will make sure not to trigger the component before you click on it

Difference between style of passing functions

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)}

Why "() => this.tick()" and "this.tick()" are not the same?

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!

Unsubscribing to a closed variable inside its own callback

I only want to listen to something once. Is this valid javascript?
const unsubscribe = obj.onFoo(x => {
unsubscribe()
// do things
})
Yes, this is a perfectly valid way of calling unsubscribe().
Even though the function is not assigned to the unsubscribe variable until after the function is constructed, it is not run until the callback is called. When the callback is called, it looks for the unsubscribe identifier and finds it in the enclosing scope. The identifier resolves to the unsubscribe function, and so unsubscribe() is called as you would expect.
This is a fairly common pattern. Just one example off the top of my head is clearing a $watch function in AngularJS – Unbinding $watch in angularjs after called

Knockout event binding unexpected behaviour

I have an event binding for the scroll event on a DIV. For debouncing the handler I introduced a function on my model which creates the debounced handler, and I'm binding this factory function in my view.
I would expect that my factory creates the debounced function and knockout will bind that to the event. Instead, it seems like knockout recreates and calls my debounced function at every event trigger, so debouncing doesn't work at all.
My view
<div data-bind="event.scroll: getScrollHandler()"></div>
My model
var viewModel = {
getScrollHandler: function(data, evt) {
return debounceFunction(function(data, evt) {
// dp the actual handling...
});
}
};
I would expect that the getScrollHandler method would execute only once at binding initialization time, and it would bind the returned function.
Instead, it seems like knockout is wrapping it all to a new function so it runs on every scroll event.
How exactly does it work in Knockout?
UPDATE
As I'm using TypeScript and this handler is a member method of a class, I'm limited to this kind of function member assignment, I cannot directly assign the debounced function as a member (or actually I could, but in some uglier way only).
Assuming you have an implementation similar to this one, the idea is it creates a new function which you then use in place of your original function. Try changing your code to this:
getScrollHandler: debounceFunction(function(data, event) {
...
})
This will create the function once and re-use it every time the scroll is activated.

Categories