What does function re creation means? How bad it is? - javascript

What does javascript re-create function every time when component re-render means?
I am basically referring to the following code.
This way of invoking function recreate function
onChange={() => this.someFunction() }
Where as this is not
onChange={this.someFunction}
I basically needs to understand how Javascript re create the functions or when it wont re create function.
Any explanation or reference guide will be highly appreciated.
Thanks a lot in advance.

your onChange prop needs a function which will be triggered when the user makes changes .
when you have this onChange={() => this.someFunction()} you are passing a function to the onChange which is correct . But now when there is a re-render we are re-creating a brand new function () => this.someFunction() again and assigning it to your onchange prop .
whereas when you have this onChange={this.someFunction} you have already created a class method named someFunction and passing it to the onChange.
The major difference between the 2 is that in your component which uses the inline function (() => this.someFunction()) your this.props.onChange === prevProps.onChange will always be false because you are creating a new function for each re-render and since function in JS are nothing but objects your reference which onChange holds will keep changing each time.

Related

React - What's the difference between {doThisFunc} , {doThisFunc()} and {()=>doThisFunc()} as onClick parameter?

I'm completely new to react and kind of mediocre in JS. Just want to know what's the difference between giving a button these parameters for its onClick event :
onClick={doThisFunc}
onClick={doThisFunc()}
onClick={() => doThisFunc()}
Recently I just got a bug where I call a function with parameter like onClick={doThisFunc(a)} and the application went "Too many re-renders. React limits the number of renders to prevent an infinite loop". But then I changed it to onClick={() => doThisFunc(a)} and It works perfectly.
Sorry for such beginner question and many Thanks for your feedback!
onClick={doThisFunc}
This means "pass the function into the onclick prop". Later, when the click happens, react will call doThisFunc, passing in the click event. This is usually the right thing to do, assuming you want the function to receive the click event.
onClick={doThisFunc()}
This means "call the function immediately, and pass its return value into the onclick prop". This is usually a mistake. You would only do this if doThisFunc was a factory that creates click-handler functions, which is rare.
onClick={() => doThisFunc()}
This means "create a new function with the text () => doThisFunc(), and pass it into onClick". Later, when the click happens, react will call your new function, which will in turn call doThisFunc.
This approach is sometimes just a more verbose way of getting the same end result as option 1. But it does have the benefit that you can pass whatever values you want into doThisFunc, so if you want something other than the event to be passed in, you would use this.

React hooks onclick event with multiple params without unnecessary rerender?

I am using react hooks and functional components and was wondering how I can add multiple params to an react onClick event.
I know there are different options to achieve this. In the past I used this style below (from https://reactjs.org/docs/handling-events.html):
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
But now I am facing this exact described problem from the official react docs. I am getting to many rerenders because of these arrow functions in the onClick attribute:
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 have put my function already in a useCallback hook. But if I use this function in a onClick event with an arrow function it will trigger rerenders again.
If I change it to the function reference only it is not triggering rerenders.
So far this is fine.
But: How do I add multiple parameters to this functionreference when using react hooks and functional components.
Will I get by default always the e (event parameter?) as first parameter?
Can somebody explain to me when and how I am getting the react event parameter and when I will not receive this event?
How can I add multiple params beside the event parameter in my onClick attribute?
For example:
What if I have this function and want to use it in the react onClick attribute, prevent unnecessary rerender and add multiple different parameter in the function call
const myClickFunction = (e, value1, value2, value3) => {
// ...
}
// this would trigger rerenders because of the arrow function how do I prevent this?
<button onClick={(e) => myClickFunction(e, "input1", "input2", "input3")}>
Click me
</button>
One trick I like to use in this case is to "bind" the parameters to rendered element using data attributes
const myClickFunction = (e) => {
const value1 = e.currentTarget.getAttribute('data-value1')
const value2 = e.currentTarget.getAttribute('data-value2')
const value2 = e.currentTarget.getAttribute('data-value2')
}
// this would trigger rerenders because of the arrow function how do I prevent this?
<button onClick={myClickFunction} data-value1="a" data-value2="b" data-value3="c">
Click me
</button>
This way you can memoise your function using useCallback safely and you can reuse the same function if you want to pass it to array of children for example. This is not ideal, you couple parents and children and you can only use data which is serializeable to string (basically only primitives).
Better solution would be to store your values somewhere out of component tree so you can access them without closures (for example in redux-thunk you don't need to pass a lot of stuff around, you can just get data you need from store directly by calling getState)

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.

Calling a method vs using a function to call a method

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.

this.setState is not a function, react native

I am aware there are similar issues but none of them helped me to fix mine.
So here is my issue.
I am working with react native and using the flux dispatcher. Dispatch and register of my app dispatcher works fine. My issue is that when I want to change/set the state inside the dispatch register function I always get the error message that this.setState() is not a function. Of course I thought this must be a binding issue then (writing in es6), so I tried all sorts of binding "this" but I still can't get it work. Has anyone any idea why?
Here is that bit of code that doesn't work:
testDispatcher() {
AppDispatcher.register( (action) => {
if ( action.action === TEST_ACTION ) {
// I tried setting state inside here
this.setState({
view: action.view
}).bind(this); // with or without this bind doesn't make a difference
// I also tried having a function outside of this function where I set the state.. this doesn't work either.
//this.updateView('home').bind(this);
console.log('dispatch register');
}
});
}
I also tried to console log "this" inside my register function and "this" does return my app class.
The => binds this to the scope of testDispatcher(). That's probably not what you want. In this case I think you should drop the => notation but simply a regular anonymous function.
Also, this.setState(...args...).bind(this) is totally wrong. 1) The this. part indicates that the .bind(this) is redundant. 2) The syntax for binding is like: foo.setState.bind(notFoo, ...args...).
My class didn't extend from React Component, therefore this.setState was not a function.

Categories

Resources