React this.state is undefined?
I am following a beginner tutorial from Pluralsight, on form submit a value is passed to addUser
component method and I need to push userName to this.state.users
but I get error
App.jsx:14 Uncaught TypeError: Cannot read property 'users' of undefined
Component
import React from 'react'
import User from 'user'
import Form from 'form'
class Component extends React.Component {
constructor() {
super()
this.state = {
users: null
}
}
// This is triggered on form submit in different component
addUser(userName) {
console.log(userName) // correctly gives String
console.log(this.state) // this is undefined
console.log(this.state.users) // this is the error
// and so this code doesn't work
/*this.setState({
users: this.state.users.concat(userName)
})*/
}
render() {
return (
<div>
<Form addUser={this.addUser}/>
</div>
)
}
}
export default Component
When you call {this.addUser}
, it gets called, here this
is an instance of your class(component), and thus it gives no error to you because addUser
method does exist in your class scope
,
but when you are under addUser
method you are using this
to update the state
which exist in
the scope of class(component), but currently you are within the scope of addUser
method and so it gives you an error as under addUser
Scope you got nothing like state, user etc.
So to deal with this problem you need to bind this
while you are calling addUser
method.So that your method always knows the instance of this
.
So the final change in your code will look like this:-
<Form addUser={this.addUser.bind(this)}/>
OR
You can bind
this
in the constructor,because it is the place when you should intialize things because constructor methods are called first when the components render to the DOM
.
So you can do it in this way:-
constructor(props) {
super(props);
this.state = {
users: null
}
this.addUser=this.addUser.bind(this);
}
And now you can call it in normal way as you did before:-
<Form addUser={this.addUser}/>
I hope this will work,And I made it clear to You.
@Vinit Raj's approaches works perfectly - tho i prefer to use the arrow function syntax like so.
<Form addUser={ () => this.addUser() }/>
Using an anonymous function like this, you don't need to bind it anywhere.
If you prefer using arrow function do this. The arrow function syntax as like below
addUser = event => {
const { value } = event.target;
console.log("value", value);
}
To prevent this function being called on every render or re-render you need to
Change
<Form addUser={this.addUser}/>
To
<Form addUser={() => this.addUser()}/>
So that addUser gets called only when event is happened/triggered