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);
}
Related
I am writing a react application, and for some reason I can not wrap my head around this issue. Below is a snippet, the only thing that should be needed:
onFirstNameChange(event: any){
console.log(event.target.value)
// this.setState({
// firstname: event.target.value
// })
}
The commented out code will not run, it says it can not read properties of undefined. However when I log the events value it does it perfectly. Any ideas on why this is happening? It is an onchange event. It is also deeply nested, however the value does make it back.
React components written in an ES6 class, do not autobind this to the component's methods. There are 2 solutions primarily. You may use choose either:
Either explicitly bind this in constructor
constructor(props) {
super(props);
// rest of code //
this.state = {
firstname: '',
};
// rest of code //
this.onFirstNameChange = this.onFirstNameChange.bind(this);
}
Or use ES6 Arrow Function
onFirstNameChange = (event: any) => {
console.log(event.target.value);
this.setState({
firstname: event.target.value
});
}
As Brian stated, I also believe the error saying that it cannot read property of undefined, is likely saying it cannot read property setState of undefined, because "this" is undefined.
This is most likely caused by providing the onFirstNameChange handler without leveraging a closure, bind, or arrow function to bind the value of this to the "this" value you are expecting.
My guess is your code leveraging the on change handler looks like the following:
<input type="text" value={this.state.value} onChange={this.onFirstNameChange} />
You can refer to the "Handling Events" page (link here) of the React documentation, you will find the following about midway down the article:
You have to be careful about the meaning of this in JSX callbacks. In
JavaScript, class methods are not bound by default. If you forget to
bind this.handleClick and pass it to onClick, this will be undefined
when the function is actually called.
This is not React-specific behavior; it is a part of how functions
work in JavaScript. Generally, if you refer to a method without ()
after it, such as onClick={this.handleClick}, you should bind that
method.
If calling bind annoys you, there are two ways you can get around
this. If you are using the experimental public class fields syntax,
you can use class fields to correctly bind callbacks.
SOLUTIONS: I've included examples of the 3 possible solutions below to bind the value of this, depending on your preference:
Option 1 - Assuming this is a class based component, which I am based on the syntax shown, you can bind the method in the constructor:
constructor(props) {
super(props);
this.onFirstNameChange.bind(this);
}
Option 2 - Update method definition to public class fields syntax with an arrow function to bind "this": (See here)
onFirstNameChange = (event: any) => {
console.log(event.target.value)
this.setState({
firstname: event.target.value
})
};
Option 3 - Update onChange callback with anonymous arrow function to bind this value:
<input type="text" value={this.state.value} onChange={() => this.onFirstNameChange} />
Note on option 3 from React Docs:
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 understand the concept of constructors in OOP languages like C++. However, I am not entirely sure when to use a constructor in REACT. I do understand that JavaScript is object oriented, but I am not sure what the constructor is actually 'constructing'.
When rendering a child component, do you need a constructor in the child component? For example:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
error: null
}
}
render () {
return (
<React.Fragment>
<ChildComponent data={this.state.items}></ChildComponent>
</React.Fragment>
)
}
}
I will keep the example short for the sake of brevity. But, why would do you need a constructor? And would you need a constructor in the child component for props?
It is possible that my ES6 knowledge is not up to snuff.
If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component.
The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.
Typically, in React constructors are only used for two purposes:
Initializing local state by assigning an object to this.state.
Binding event handler methods to an instance.
https://reactjs.org/docs/react-component.html#constructor
A constructor function is NOT required at all.
State initialization can be done directly in the body of a class and function can be assigned to properties as described below, Technically these are known as class properties, it may land up soon in native javascript, yet because almost all of us use Babel transpiler for React projects, we can use that syntax
class Comp extends React.Component {
/*
* generally we do not need to put the props in state, but even if we need to.
* then it is accessible in this.props as shown below
**/
state={ first: 1, second: this.props.second }
handler= (token) => {
this.setState(prevState => ({first: prevState.first+1}));
}
render() {
return <div onClick={this.handler}>{this.state.first} and {this.state.second } </div>
}
}
Read more details about class properties and removing constructor from react class component over here.
https://hackernoon.com/the-constructor-is-dead-long-live-the-constructor-c10871bea599
Linke in your example, it's useful use constructor when you need to initialize your state, or bind some event-listener-function
<element onClick={this.handler} />
this.handler = this.bind.handler(this); inside the constructor
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
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.
Which is better (more performant), if one it is:
A:
class Man extends React.Component {
constructor(props) {
super(props)
this.talk = this.talk.bind(this)
this.state = {}
}
talk() { .. }
render () {
return <div onClick={this.talk}>talk!</div>
}
}
B:
class Man extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
talk() { .. }
render () {
return <div onClick={this.talk.bind(this)}>talk!</div>
}
}
C:
class Man extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
talk() { .. }
render () {
return <div onClick={() => this.talk()}>talk!</div>
}
}
I think that calling the bind method directly in the render method could be negligible, but after all the render method is called ton of times. I want to understand if making a change in a big codebase is it worth it or not.
As per React DOC (last para of the page):
onClick={(e) => this.handleClick(e)} and onClick={this.talk.bind(this)}
The problem with this syntax is that a different callback is created
each time the component 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 property initializer
syntax, to avoid this sort of performance problem.
MDN DOC:
Function.prototype.bind():
The bind() method creates a new function always.
Binding method in the constructor:
However if you bind the method in the constructor:
this.handleClick = this.handleClick.bind(this);
and use it like this:
onClick={this.handleClick}
It will create only one instance and use that instance always. So binding method in the constructor means you end up binding only once and you can re-use it as many times, even if the render() method is called multiple times the same function will be used.
property initilizer syntax (this is experimental syntax.):
By this way you don't need to bind all the methods in the constructor, and it will not create multiple callbacks also.
handleClick = () => {
.....
}
The best solution will be auto binding internal methods. using arrow functions as methods.
So we don't rely on the constructor to bind the internal methods, and for example having multiple internal methods will just increase the number of lines of your files unnecessarily
Here is an implementation of what I'm saying:
class Man extends React.Component {
constructor(props) {
super(props)
this.state = {};
}
talk = () => { .. }
render () {
return <div onClick={this.talk}>talk!</div>
}
}
In order for this to work, you should use transform-class-properties from Babel Stage 2 preset
If we are to define 'more performant' as something that requires the least amount of computational resource, then option A (binding in the constructor) would be the most performant.
As you state, this is because this only happens once during the creation of an instance of the component. The .bind returns a newly bound function which is referenced later on.
The latter two options will be creating new functions (bound or anonymous) on every render, which is not necessary in this context.
I think you should do binding in constructor as calling bind returns a new function. It should be called one time for performance reasons. In you call it in render, bind will be called on every render and will return a new reference each time.