Calling a method vs using a function to call a method - javascript

Suppose we have a method inside a class like this
class Blog extends Component {
postClicked = (id) => {
this.setState({selectedPostId: id})
}
render () {
const newPosts = this.state.posts.map(el => {
return <Post key={el.id}
title={el.title}
author={el.author}
onClick={this.postClicked(el.id)}/>
})
return
//something
{post}
}
}
}
Now, What is the difference between calling the handler like this
onClick={this.postClicked(el.id)} and onClick={() => this.postClicked(el.id)}
Would appreciate if someone can tell me the difference in general

after Ecmascript 6 javascript was introduced with is arrow function link
here ()==>{//code} is a similar as a function() or anonymous function
tell me if you find out what you want

The first option, "this.postClicked(el.id)", will actually call the method, "this.postClicked", with the "el.id" argument, each time the component renders (probably not what's intended).
The second option, "() => this.postClicked(el.id)", will only call the method, "this.postClicked", with the "el.id" argument, when "Post" is clicked.
Overall, if you can find a way to put the "el.id" argument into an "id" or "name" prop on the component
<Post id={el.id} />
then you can do:
<Post
id={el.id}
onClick={this.postClicked}
/>
this.postClicked = (event) => {
const { id } = event.target;
...
}
This last option avoids the use of an unnamed function. If you use an unnamed function, it will cause unnecessary re-renders. React cannot tell that an unnamed function is the same when it's checking whether or not it should re-render, by considering if the props of a component have changed. It considers the unnamed functions to be a new prop each time it checks, causing an unnecessary re-render each time.
Overall, it won't break your app, but it slows down performance slightly if you do it enough. It comes up especially if you start using React Motion (you'll really notice a difference there). It's best to avoid unnamed functions if possible.

you can read this blog it wil clear the things https://medium.com/#machnicki/handle-events-in-react-with-arrow-functions-ede88184bbb

Differences are,
First method is a wrong implementation and it wont give the intended result, where as second one will work.
In the first method you are making a function call, in second one you are assigning a function's signature to onClick.
It is like the combination of below two statements.
var variableName = function(){//some content};
onClick={variableName}

It looks like you question has already been answered. Just a side note though: remember that when assigning your method with an arrow function
onClick={ () => this.method() }
a new anonymous function is created on every re-render. So if the method doesn't need any arguments, it's better to reference the method directly (without parentheses so it's not invoked).
onClick={ this.method }

The first will call the function every time render is done.
The second will do what you want - call it onClick.

Related

Using .bind() in functional React component, is it recommended?

I saw this syntax below during our code review, it's my first time seeing it, I couldn't find any article online of it being used/recommended - usually I would opt for arrow function or useCallback in this use case. Just curious if anyone else here used this, and if yes, would you be able to provide some references or an article saying it's safe or recommended to use it.
function DummyComponent({ onBtnClick }) {
const [data, setData] = useState('some-data-that-only-exists-here');
return (
<div>
<button onClick={onBtnClick.bind(null, dummyData)} />
</div>
)
}
I was told that this prevents the function from being recreated on rerenders. Also, during writing of tests, it passes a class which seems to be the class of the HTML button as the 2nd argument when onBtnClick is triggered which is one of the reason why I didn't approve of this and needed some references.
While it's technically possible, the use of .bind or .call or .apply instead of an anonymous function is usually done to change the this inside the function. Here, you don't care about this, so it'd probably make a bit more intuitive sense to read and write if you used an anonymous function instead.
<button onClick={() => onBtnClick(dummyData)} />
Or make a higher-order function outside, before returning the JSX:
const makeOnBtnClick = arg => () => onBtnClick(arg);
<button onClick={makeOnBtnClick(dummyData)} />
I was told that this prevents the function from being recreated on rerenders.
No, a new function is created every time the render part (with the .bind runs), so a new function gets attached as the click handler every time. If this is something you're really worried about (which you probably shouldn't be), useCallback would be one way to have a more persistent function that doesn't have to be removed/recreated when rendering - just like you mentioned.

Where do function parameters come from in javascript?

I am using the following code:
handleOwnerMode = ownerChecked => {
this.setState(prev => ({ ownerChecked, showOwner: !prev.showOwner}))
// this.setState(prev => ({ ownerChecked: !prev.ownerChecked, showOwner: !prev.showOwner }))
}
Inside the render is
<Switch onChange={this.handleOwnerMode} checked={this.state.ownerChecked} />
OnChange, I somehow was able to receive what was changed about ownerChecked. Why is this the case? I didn't write onChange={this.handleOwnerMode(event.value)} or anything like that...
Also, for setState. I normally just use this.setState( { state: newState} ), but now I can somehow pass in the previous state with this.setState( prev => {} ). Is there defined overloading somewhere that lets me do this?
Thank you.
OnChange, I somehow was able to receive what was changed about
ownerChecked. Why is this the case? I didn't write
onChange={this.handleOwnerMode(event.value)} or anything like that...
In both cases you have passed a function (callback) to "receivers". First time to Switch Component, second time to React. Each of them can call your function/callback using any parameter they want. This is how normally callbacks are used.
Is there defined overloading somewhere that lets me do this?
Yeah probably setState checks if you passed a function to it and behaves differently: e.g. gives you previous state and calls your function. If you pass an object to it, it doesn't do that.
React events are synthetic so that even when yo do not pass any event parameters, function takes it. Take a look at these. More information 1, More information 2.

Choosing the correct way to call function in stateful component

So i am having tough time figuring/understanding the correct way to call method inside a class in javascript for example
consider we have stateful component with various method like
addIngredientHandler = (type) => { //Adds one to the state of ingredient }
and
purchasingHandlerOpen = () => this.setState({purchasing: true}) //will show a order summary pop-up if we have more than one ingredient
We pass both of them to child component (using props) by calling them in a return of our stateful component like this
<BuildControls
ingredientAdded={this.addIngredientHandler}
purchasingHandlerOpen={this.purchasingHandlerOpen}
purchasableHandler={this.state.purchasable} />
and In our stateless child component we do
<BuildControl
ingredientAdded={() => props.ingredientAdded(el.type)}
/>))}
<button className={Classes.OrderButton} disabled={!props.purchasableHandler} onClick={props.purchasingHandlerOpen}>Order</button>
</div
Here we have use this at one place
ingredientAdded={() => props.ingredientAdded(el.type)}
and this in another
onClick={props.purchasingHandlerOpen}>
So my question is when do we call a method/function using {() => props.ingredientAdded(el.type)} and when do we use {props.purchasingHandlerOpen} and when do we probably do something like {props.purchasingHandlerOpen()}
Slight Note: In the above example where i do
<button className={Classes.OrderButton} disabled={!props.purchasableHandler} onClick={props.purchasingHandlerOpen}>Order</button>
If I do something like {props.purchasingHandlerOpen()} it throws infinite render error message, I I do something like {() => props.purchasingHandlerOpen} the button does not work.
First of all, you have to understand that the thing you're passing here are just functions, so there is nothing principally different in those 2 ways
There are few points you need to consider though:
First: since react.js uses shallow comparison, every time you're passing
ingredientAdded={() => props.ingredientAdded(el.type)}
you're actually pass function created just now, so it may cause unneeded calls of your children render function (you could easily avoid this by using shouldComponentUpdate though). This could lead to possible performance issues on big react trees so that you second approach is preferred.
Second: you could easily mix a some value via your first approach, something like
ingredientAdded={() => props.ingredientAdded(el.type, SOMETHING_FROM_STATE)}
Third. You can easily modify your event handlers and pass down them in react tree by generating functions which return functions:
class App extends React.Component {
generateFunction(something) {
return (arg) => {
this.props.myFunction(something, arg)
}
}
render() {
return (
<div>
<FirstComponent onClick={this.generateClickFunction('First')} />
<SecondComponent onClick={this.generateClickFunction('Second')} />
</div>
}
}
}
UPD
onClick should always receive function, not its results, like that:
<button ... onClick={props.purchasingHandlerOpen} />
if you are changing onClick to {props.purchasingHandlerOpen()} you are calling the function, so you're passing its result to props.
If you are changing onClick to {() => purchasingHandlerOpen} you are passing undefined (it's not a props.purchasingHandlerOpen, but purchasingHandlerOpen is undefined) so that React considers there is no a callback passed to the props
{() => props.ingredientAdded(el.type)} creates a new funciton which binds the el.type, see arrow functions
{props.purchasingHandlerOpen} does nothing since we do not execute the function (there are no (), call, apply). We simply pass the function reference.
{props.purchasingHandlerOpen()} runs the function.

JSX props should not use .bind() - how to avoid using bind?

I have a container that I need to change the UI form showing the form or showing a success page.
The container has a state.showSuccess and I need the MyFormModule to be able to call the container to change the state.
The below code works but I'm getting the following warning:
JSX props should not use .bind()
How can I get this to work without using .bind()?
...
const myPage = class extends React.Component {
state = { showSuccess: false };
showSuccess() {
this.setState({
showSuccess: true,
});
}
render() {
const { showSuccess } = this.state;
if (showSuccess) {...}
....
<MyFormModule showSuccess={this.showSuccess.bind(this)} />
You should first understand WHY this is a bad practice.
The main reason here, is that .bind is returning a new function reference.
This will happen on each render call, which may lead to a performance hit.
You got 2 options:
Use the constructor to bind your handlers (this will run only once).
constructor(props) {
super(props);
this.showSuccess = this.showSuccess.bind(this);
}
Or create your handlers with arrow functions so they will use the
lexical context for this, hence you won't need to bind them at
all (you will need a babel plugin):
showSuccess = () => {
this.setState({
showSuccess: true,
});
}
You should not use this pattern (as others suggested):
showSuccess={() => this.showSuccess()}
Because this will as well create a new function on each render.
So you may bypass the warning but you are still writing your code in a bad practice design.
From the ESLint docs:
A bind call or arrow function in a JSX prop will create a brand new
function on every single render. This is bad for performance, as it
will result in the garbage collector being invoked way more than is
necessary. It may also cause unnecessary re-renders if a brand new
function is passed as a prop to a component that uses reference
equality check on the prop to determine if it should update.
Use an arrow function when defining showSuccess
showSuccess = () => {
this.setState({
showSuccess: true,
});
}
Use an arrow function since they automatically inherit the this context of wherever they are defined.
showSuccess={() => this.showSuccess()}
Here is a link to the facebook documentation on this subject, which lists this method among others as a solution. Interestingly, they also list using .bind in the prop as one of the solutions, even though it produces a warning when actually used.
From that documentation, you'll note that this is a potential performance issue, since the function will be recreated on every render:
Note:
Using an arrow function in render creates a new function each time the
component renders, which may have performance implications (see
below).
But also from the same link:
Is it OK to use arrow functions in render methods? Generally speaking,
yes, it is OK, and it is often the easiest way to pass parameters to
callback functions.
If you do have performance issues, by all means, optimize!
So I would say if your component will be re-rendering very frequently, you should use one of the other solutions: bind in the constructor, or define the method with an arrow function in the first place. But if not, use whatever method seems cleanest to you.

react-native - calling functions as arguments

I've got a sneaking suspicion this question might be more todo with JavaScript and/or specifically ES6 than React-Native but I'll try. I have got the following component:
export default class Body extends Component {
componentWillMount() {
this.refresh();
}
clickme() {
console.log('I have been pressed!!!!!');
}
refresh() {
this.props.populateGrid();
}
render() {
return (
<View style={styles.body}>
<Grid inGrid={this.props.grid} />
<Button
onPress={this.clickme}
title={'PressMe'}
/>
</View>
);
}
}
First, I passed 'this.clickme()' to onPress. It didn't work. It was only after removing the braces it started working. Why? Don't we usually call a function including the ()? Also sometimes, you have to pass it in the following format something={() => this.clickme()}. Why/When?
So when do we call function as:
1. {this.clickme}
2. {this.clickme()}
3. {() => this.clickme()}
Thank you.
Short answer:
1 and 3 as you define in your question are effectively the same for Button.onPress -- they are passing in references to function bodies. However, #3 is also defining a new function inline, though it is defined in a very lightweight way. #2 is attempting to call the function inline. You might want to do this (#2) in some cases where you need to pass a number or boolean or string value to a property rather than a callback function as Button.onPress requires.
Longer answer:
The syntax required is defined by the signature of the method you're passing data to on the react component. In this case, we're talking about Button.onPress, which has the signature () => {} -- which means it takes in a callback function and won't pass any arguments to it when called. You don't want to call the function immediately, since the user is not clicking when you define the component. They are clicking some random time later.
Since you need to pass in a function and not its result, you don't want to include the () at the end of the function name. The parentheses will cause the function to be run immediately, whereas the name alone will simply pass a reference to the function body. That reference will be later called by Button.onPress to handle the user interaction.
A lot of JavaScript (and React) is written with a pattern of passing around function references and later calling those functions from within other functions. If you're not familiar with that pattern, definitely spend some time reading about callback patterns.
() => {} is also a shorthand way to define an inline anonymous function. It's called an arrow function, and it can have some performance gains over defining separate function bodies.
More info here:
() => {} (arrow function) documentation on MDN
Callback documentation on MDN

Categories

Resources