ReactJS bind(this) - javascript

I'm following a tutorial to update states in ReactJS. I came across this line in the tutorial this.updateLanguage = this.updateLanguage.bind(this) and I don't understand what is going on. I understand the basics of this and bind, but I've never seen it done like this before. Can someone please explain? The full code:
var React = require('react');
class Popular extends React.Component {
// constructor to set default state
constructor (props) {
super(props);
this.state = {
selectLanguage: 'All'
};
// I don't understand this line
this.updateLanguage = this.updateLanguage.bind(this);
}
// updates state
updateLanguage(lang) {
this.setState(() => {
return {
selectLanguage: lang
}
});
}
render() {
var languages = ['All', 'JavaScript', 'Ruby', 'Java', 'CSS', 'Python'];
return (
<ul className='languages'>
{languages.map((lang) => {
return (
// adds listener to current state
<li style={lang === this.state.selectLanguage ? {color: '#d0021b'}: null}
onClick={this.updateLanguage.bind(null, lang)}
key={lang}>
{lang}
</li>
)
})}
</ul>
)
}
}
module.exports = Popular;

DOM callbacks such as click events will set the this context to the DOM element itself, in this case the li. Try removing the part you don't understand and see what happens - you'll see something like this.setState is not defined, because that function isn't defined in the context of the li element (it's basically looking for li.setState).
What bind is doing on that line is ensuring that whenever that function gets called, it will get called with the this context we want, in this case the Popular component - e.g. Popular.setState.
These days it's getting more and more common to see folks just using fat arrow syntax as a shorthand to preserve the this context - e.g. in this case onClick={ () => this.updateLanguage(lang) }.
(note for those concerned about performance: the fat arrow approach is cleaner but somewhat controversial since it's repeatedly declaring the function on every single render. That said, some folks claim there is minimal or no significant performance impact.)

If you not getting the bind(this) in constructor then its not but one of the way to avoid binding in render
Now why we need bind(this) in render let say we generally use
onChange={this.handleChange.bind(this)}
These approaches assume that you’re declaring React components using ES6 classes. If you use an ES6 class, React no longer autobinds.
So, this is the One way to resolve this is to call bind in render.

Related

Does calling curried function in render have negative performance impact?

I've read that it's good practice to declare function as component's method instead of inlining it in render, because every time parent component is rendered it creates new function and messes up with child's shouldComponentUpdate.
I.e. this:
<button onClick={this.handleClick} />
is better than that: <button onClick={e => someAction(e)} />
But what about curried functions? Is the following considered as creating new function?
class Parent extends Component {
handleClick = data => event => someAction(data);
render() {
const data = 123;
return <button onClick={this.handleClick(data)} />;
}
}
I know that the "performance impact" may be unnoticable there, but I find partially applicating function paramaters while passing down the component tree very convienent and I'm wondering if it's against best practices.
Yes it has negative performance impact because of the extra function invocation. But do you really have to worry about it? Most likely not. There are popular React patterns that use closures in render, like https://reactjs.org/docs/render-props.html Measure first to avoid spending energy on imaginary performance bottlenecks.
Yes. Every time you execute handleClick you will get in return a new function. In other words purpose of handleClick is to return a new function. If you remove some of the implicit syntaxes you will get:
handleClick = data => {
const innerFunction = event => someAction(data);
return innerFunction;
}
Side note: I've read some benchmarks that such performance impact by creating functions in render may have less impact than most people think.

React performance and passing down arrow functions as props

I've recently learned that passing down object literals or functions as props can cause unnecessary re-renders. As I am doing an audit on my app, I am finding some cases where I have common components that have callbacks on events that do different things. It's unclear to me what the most elegant way to handle this would be.
So for example in my app I have a component called SharedBtn that is used all over the app multiple places and in large loops. This button has an onClick listener. But in every instance this onClick is used we are passing down a different function to do a different thing every time.
Example:
https://codesandbox.io/s/k31120vnyo
I read this related article with examples. But their solution is to move the onClick logic to the shared component. This would be ugly for me as it is used in many different spots with many different handlers. How could I have the multiple click handlers without moving the click handling logic to the SharedBtn component itself?
You could create a small wrapper component for each special instance.
class IndexSharedButton extends React.PureComponent {
handleClick = e => {
this.props.onClick(e, this.props.index);
};
render() {
return <SharedBtn copy={this.props.copy} onClick={this.handleClick} />;
}
}
class AnimalSharedButton extends React.PureComponent {
handleClick = e => {
this.props.onClick(this.props.animal, this.props.type);
};
render() {
return (
<SharedBtn copy={this.props.animal} onClick={this.handleClick} />
);
}
}
You could also manually manage caching the bound handlers, but IMO that's pretty ugly and much less idiomatic.
Also, I think it goes without saying that you shouldn't worry about this much at all if you haven't measured it to be an actual issue. Re-renders don't happen that often, and with shouldComponentUpdate should happen even less. Optimizations like this add more code for little benefit.
Most of the time the performance hit is negligible. But the correct way to mitigate this in the age of hooks is via useCallback.
import { useCallback } from "react"
const MyComp = () => {
const func = useCallback(() => doSomething(), []);
return <OtherComp func={func}/>
};

Reactjs: Passing parameter in onClick method without performance loss [duplicate]

This question already has answers here:
How to avoid bind or inline arrow functions inside render method
(4 answers)
Closed 4 years ago.
I am new to React and I have been told that when passing methods to the onClick handler you should not:
use inline arrow functions
call .bind(this, parameter)
As they both will create a new function on every single render, which has implications or performance
In my code I have a parent component sending a method (asideSelected()) as a prop to the child component. In the child component, I want to call this method with a parameter that my parent component receives. I have created the following solution:
Parent:
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
selected: ""
};
this.asideSelected = this.asideSelected.bind(this);
}
asideSelected(selected) {
this.setState({
selected: selected
});
}
render() {
return (
<Aside
selected={this.asideSelected}
/>
);
}
Child:
export default class Aside extends Component {
constructor(props) {
super(props);
this.selected = this.props.selected.bind(this);
this.showSelected = this.showSelected.bind(this);
}
showSelected(e) {
let selected = e.target.className;
this.selected(selected);
}
<div className="profile" onClick={this.showSelected} src={chat}></div>
}
This solution appears to be working, however, so does using inline arrow functions and binding inside of the onClick, I've never seen "bad" re-render and so I don't know if this is actually any different from the other ways of doing it. If it is unclear what I am attempting to do I am using the events target to pass as a parameter instead of doing it directly inside onClick. I am worried that this is a clunky or sub-par solution.
Any input welcome,
Thank you
The render is triggered by the setState().
Any time you update the state: this.setState(), the component and its children will re-render, you may read the doc here
It is unusual and unnecessary to bind to functions in the constructor of a react class. When you add a new function in the react object, for instance asideSelected(){ ... } in your example above, this function is bound to the prototype of the react object.
By adding this.asideSelected = this.asideSelected.bind(this); in your constructer, you create a new instance of asideSelected directly to the object. By doing this you add 2x the same functions.
Regarding the arrow functions, that is just ES6 syntax that auto scopes you code to this without the need to use .bind(this). This is just syntactical ES6 magic and should in theory not have any performance hit and makes your code look nicer.
Binding should be done in constructor and reason for it given in following link.I am not writing all blog here, because it's little bit lengthy. Let me know, if you don't understand it, then I will try to give more explanation.
Link: https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56

React Native: this.setState is not a function

I see a number of questions on here relating to this same issue, but it seems none match the issue I'm having, and are a bit more complex.
I am in the process of learning ReactJS and React Native. I'm in the midst of reading and following the code examples from "Learning React Native" book here: https://github.com/bonniee/learning-react-native
For some reason, calling this.setState in the code below when the handleTextChange function is called, causes the "this.SetState is not a function." error. My question is why? Unlike other questions about this same issue, I don't believe my call to this.stateState is buried in a callback function or if statement. Why is it undefined?
Here is my code:
class WeatherProject extends Component {
constructor(props) {
super(props);
this.state = {
zip: "",
forecast: null
};
}
_handleTextChange(event) {
this.setState({zip: event.nativeEvent.text});
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
You input {this.state.zip}.
</Text>
<TextInput
style={styles.input}
onSubmitEditing={this._handleTextChange}/>
</View>
);
}
}
Do not use bind inside a render. bind is a rather expensive operation and should only happen once. you have two options:
either bind the function in the constructor:
this._handleTextChange = this._handleTextChange.bind(this);
or use arrow function:
onSubmitEditing={(e) => this._handleTextChange(e)} />
Edit
Apparently arrow functions inside render is also a bad practice (Thx to Adam Terlson in the comments and answer below). You can read eslint docs which states:
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.
Using arrow functions is obviously not as bad as using bind, but nevertheless should be avoided.
Regarding arrow function you also need to change _handleTextChange(event) function. Other answers didn't talk about how to change normal function to arrow function.
You need to change handler function, from:
_handleTextChange(event) {
this.setState({zip: event.nativeEvent.text});
}
To:
_handleTextChange = event => {
this.setState({zip: event.nativeEvent.text});
}
The issue is context binding, as identified in the other comments and answers here.
However, the performance of bind itself is a non-issue. The way-more-relevant issue is that using bind or arrows in your render methods creates a new function on each render, resulting in a change of props for the child that receives them, forcing a re-render.
You have two viable options:
class WeatherProject extends Component {
constructor(props) {
super(props);
this._handleTextChange = this._handleTextChange.bind(this);
}
// ...
}
Or you can use the class property notation and assign arrow functions if you're using the babel plugin for it.
class WeatherProject extends Component {
constructor(props) {
super(props);
// ...
}
handleTextChange = (event) => {
this.setState({zip: event.nativeEvent.text});
}
// ...
}
I strongly recommend you use the eslint package with the react recommended rules enabled. It will catch errors like using bind/arrows in your render, as well as tell you that underscore prefixed functions are ugly and totally not necessary in React. :)
this.setState is not a function--- Solved using this
let that = this;
that.setState({membersArray:response.data})
I had the same problem when trying to set the state. when I bind the function inside the constructor, the issue gets solved. check with below binding
constructor(props) {
super(props);
this.state = {
zip: "",
forecast: null
};
this._handleTextChange = this._handleTextChange.bind(this);
}

Runtime context (this) of the function comes from this.props

We always use like this:
var MainComponent = React.createClass({
changeHandler() {
this.setState({
foo: 'bar';
})
},
render() {
return (<SubComponent onChange={this.changeHandler} />)
}
})
var SubComponent = React.createClass({
render() {
return (<button onClick={this.props.onChange}>Change</button>)
}
})
when we call this.props.onChange in SubComponent, we actually call changeHandler of MainComponent.
I suddenly realize that the context of changeHandler has been changed when pass to SubComponent using this.props, the this inside changeHandler should have been changed to this.props.
But as we all know, when we call changeHandler inside Subcomponent, the this in changeHandler is still MainComponent.
So I guess there may be some 'binding' when when pass function from MainComponent to SubComponent using this.props. The context of changeHandler is bound to MainComponent.
I add an console.log(this.props) in SubComponent's render, and I find some properties been add to this.props.onChange:
__reactBoundArguments: null
__reactBoundContext: point to Constructor MainComponent
__reactBoundMethod: point to function changeHandler
I think these are about the 'binding', but I don't know how they actually work.
Could someone please tell me something detail about this context binding, it's really nag me a lot. How does React do that?
When you define your components with React.createClass() there's a bit of auto-binding behind the scenes.
Your onChange={this.changeHander} effectively becomes onChange={this.changeHandler.bind(this)}. The reason for this is because it's generally what you want. This is documented here:
https://facebook.github.io/react/blog/2013/07/02/react-v0-4-autobind-by-default.html
Note however that if you define your components using the ES6 class syntax, this auto-binding does not occur. This was a deliberate decision to keep the behaviour the same as typical JavaScript classes. This is documented here:
https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html
Autobinding
React.createClass has a built-in magic feature that bound all methods to this automatically for you. This can be a little confusing for JavaScript developers that are not used to this feature in other classes, or it can be confusing when they move from React to other classes.
Therefore we decided not to have this built-in into React's class model. You can still explicitly prebind methods in your constructor if you want.

Categories