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().
Related
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 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 !
I am trying to test a function in a redux container but the issue is barely about redux or react. Basically the fetchData function I am trying to test, takes two functions as parameters and calls them.
What I was hoping to do was to have two anonymous stubs and pass them to the function this way:
var firstStub = sinon.stub().withArgs(mockResponse).returns('success');
var secondStub = sinon.stub().withArgs(mockResponse).returns('success');
AccountApp.fetchData({ firstStub , secondStub });
When this happens my function fetchData complains about the firstStub and secondStub not being a function. I know they are stub objects but if that is the case what is the correct way of managing this situation.
Passing the stubs as
AccountApp.fetchData({ firstStub , secondStub });
seems to be the culprit, because this means that you actually (after ES6 desugaring) invoke this:
AccountApp.fetchData({ firstStub: firstStub, secondStub: secondStub });
and this means that your fetchData() function would need to have an implementation like this:
function(args) {
// ....
args.firstStub(params);
args.secondStub(params);
// ...
};
I seriously doubt that your production code refers to those callbacks as "stubs". So you probably want to invoke the function like this:
AccountApp.fetchData(firstStub, secondStub);
I have a function that looks like this:
function outer() {
function inner_1() {
alert('inner_1');
}
function inner_2() {
alert('inner_2');
}
function inner_3() {
alert('inner_3');
}
inner_1();
inner_2();
inner_3();
}
I need to call outer(), but I want to replace inner_1() with another function.
I have tried this:
new_outer = outer;
new_outer.inner_1 = function() {
alert('my new inner function');
};
If I try to call the newly redefined inner_1 like this:
new_outer.inner_1();
it works as expected ('my new inner function' is alerted).
But if I try to call the outer function:
new_outer();
the old version of inner_1 is called.
I want to redefine inner_1 and the call outer. How can I achieve this?
This seems like a really bad idea so I am not going to post any code. However, if you are pursuing the answer for "educational purposes only", I will just hint that although you cannot easily redefine a function from outside its scope (as per your example), there is nothing stopping you from redefining a function attached to a function object.
I do think, however, there is a better solution to whatever the problem you are trying to solve is.
I'm frequently using this structure:
var example = (function () {
function privateFn2 () {
...
}
function privateFn1 () {
...
}
return {
publicMethod1: function () {...
},
publicMethod2: function () {...
}
};
}());
What I want to know is this: If privateFn1 is the only function/method that calls privateFn2, is it regarded as better practice to set it up as follows?
EDITED for clarity
var example = (function () {
function privateFn1() {
function privateFn2() {
}
...
privateFn2();
}
return {
publicMethod1: function () {...
},
publicMethod2: function () {...
}
};
}());
This is a wildly simplified example, of course. The issue is that I have lots of private functions, and I'm wondering whether nesting is well- or poorly-regarded. I recognise it is quite possibly a matter of preference, but any advice will be gratefully received.
Thanks.
It depends on the situation. If you have several private functions that are only relavent to yet another private function, then perhaps this is a situation where the object or class is packaging more functionality then it should be.
Here are some questions to ask:
Do these private functions have side effects? That is, are they
manipulating any closed over properties? If not, is this some generalized
logic that could be implemented statically and included
separately? Or, are these private functions manipulating a subset of
properties that could be moved to another class or object?
Are the private functions simple task specific helper functions to be used within
a larger algorithm or control function; such as a filter function for sorting an
array, or some other kind of iteration callback? If so, then it may be in-fact
cleaner to nest those functions inside and keep them out of scope of the main
object. Will any other code need these functions?
How many times will the main private function be called? If it will be called very
frequently (inside a loop or on a timer interval) then nesting the
private functions inside could incur a measurable overhead --
which would have otherwise been negligible had the private function
been called only occasionally.
There are always trade-offs to consider, thinking about these questions will help you decide what is best for your particular situation.
I would avoid your second example. Every time privateFn1 gets called, it redefines privateFn2. Why not just do it once? You might even need to use it somewhere else later on.
However, if you really want to hide privateFn2, a better solution is this:
var privateFn1 = (function () {
function privateFn2() {
// ...
}
return function () {
privateFn2();
// ...
};
})();