I am getting the following error
Uncaught TypeError: Cannot read property 'setState' of undefined
even after binding delta in the constructor.
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count : 1
};
this.delta.bind(this);
}
delta() {
this.setState({
count : this.state.count++
});
}
render() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.delta}>+</button>
</div>
);
}
}
This question is related to
javascript
reactjs
There are two solutions of this issue:
The first solution is add a constructor to your component and bind your function like bellow:
constructor(props) {
super(props);
...
this.delta = this.delta.bind(this);
}
So do this:
this.delta = this.delta.bind(this);
Instead of this:
this.delta.bind(this);
The second solution is to use an arrow function instead:
delta = () => {
this.setState({
count : this.state.count++
});
}
Actually arrow function DOES NOT bind it’s own this
. Arrow Functions lexically bind
their context so this
actually refers to the originating context.
For more information about bind function:
Bind function Understanding JavaScript Bind ()
For more information about arrow function:
Just change your bind statement from what you have to => this.delta = this.delta.bind(this);
In ES7+ (ES2016) you can use the experimental function bind syntax operator ::
to bind. It is a syntactic sugar and will do the same as Davin Tryon's answer.
You can then rewrite this.delta = this.delta.bind(this);
to this.delta = ::this.delta;
For ES6+ (ES2015) you can also use the ES6+ arrow function (=>
) to be able to use this
.
delta = () => {
this.setState({
count : this.state.count + 1
});
}
Why ? From the Mozilla doc :
Until arrow functions, every new function defined its own this value [...]. This proved to be annoying with an object-oriented style of programming.
Arrow functions capture the this value of the enclosing context [...]
if your are using ES5 syntax then you need to bind it properly
this.delta = this.delta.bind(this)
and if you are using ES6 and above you can use arrow function, then you don't need to use bind() it
delta = () => {
// do something
}
Arrow function could have make your life more easier to avoid binding this keyword. Like so:
delta = () => {
this.setState({
count : this.state.count++
});
}
you have to bind new event with this keyword as i mention below...
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count : 1
};
this.delta = this.delta.bind(this);
}
delta() {
this.setState({
count : this.state.count++
});
}
render() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.delta}>+</button>
</div>
);
}
}
You can also use:
<button onClick={()=>this.delta()}>+</button>
Or:
<button onClick={event=>this.delta(event)}>+</button>
If you are passing some params..
though this question had a solution already, I just want to share mine to make it be cleared, hope it could help:
/*
* The root cause is method doesn't in the App's context
* so that it can't access other attributes of "this".
* Below are few ways to define App's method property
*/
class App extends React.Component {
constructor() {
this.sayHi = 'hello';
// create method inside constructor, context = this
this.method = ()=> { console.log(this.sayHi) };
// bind method1 in constructor into context 'this'
this.method1 = this.method.bind(this)
}
// method1 was defined here
method1() {
console.log(this.sayHi);
}
// create method property by arrow function. I recommend this.
method2 = () => {
console.log(this.sayHi);
}
render() {
//....
}
}
You have to bind your methods with 'this' (default object). So whatever your function may be just bind that in the constructor.
constructor(props) {
super(props);
this.state = { checked:false };
this.handleChecked = this.handleChecked.bind(this);
}
handleChecked(){
this.setState({
checked: !(this.state.checked)
})
}
render(){
var msg;
if(this.state.checked){
msg = 'checked'
}
else{
msg = 'not checked'
}
return (
<div>
<input type='checkbox' defaultChecked = {this.state.checked} onChange = {this.handleChecked} />
<h3>This is {msg}</h3>
</div>
);
You dont have to bind anything, Just use Arrow functions like this:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 1
};
}
//ARROW FUNCTION
delta = () => {
this.setState({
count: this.state.count++
});
}
render() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.delta}>+</button>
</div>
);
}
}
This error can be resolved by various methods-
If you are using ES5 syntax, then as per React js Documentation you have to use bind method.
Something like this for the above example:
this.delta = this.delta.bind(this)
If you are using ES6 syntax,then you need not use bind method,you can do it with something like this:
delta=()=>{
this.setState({
count : this.state.count++
});
}
There is a difference of context between ES5 and ES6 class. So, there will be a little difference between the implementations as well.
Here is the ES5 version:
var Counter = React.createClass({
getInitialState: function() { return { count : 1 }; },
delta: function() {
this.setState({
count : this.state.count++
});
},
render: function() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.delta}>+</button>
</div>
);
}
});
and here is the ES6 version:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count : 1 };
}
delta() {
this.setState({
count : this.state.count++
});
}
render() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.delta.bind(this)}>+</button>
</div>
);
}
}
Just be careful, beside the syntax difference in the class implementation, there is a difference in the event handler binding.
In the ES5 version, it's
<button onClick={this.delta}>+</button>
In the ES6 version, it's:
<button onClick={this.delta.bind(this)}>+</button>
Adding
onClick={this.delta.bind(this)}
will solve the problem . this error comes when we try to call the function of ES6 class , So we need to bind the method.
When using ES6 code in React always use arrow functions, because the this context is automatically binded with it
Use this:
(videos) => {
this.setState({ videos: videos });
console.log(this.state.videos);
};
instead of:
function(videos) {
this.setState({ videos: videos });
console.log(this.state.videos);
};
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/[email protected]/dist/react.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/react-dom.min.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component{
constructor(props){
super(props);
this.state = {
counter : 0,
isToggle: false
}
this.onEventHandler = this.onEventHandler.bind(this);
}
increment = ()=>{
this.setState({counter:this.state.counter + 1});
}
decrement= ()=>{
if(this.state.counter > 0 ){
this.setState({counter:this.state.counter - 1});
}else{
this.setState({counter:0});
}
}
// Either do it as onEventHandler = () => {} with binding with this // object.
onEventHandler(){
this.setState({isToggle:!this.state.isToggle})
alert('Hello');
}
render(){
return(
<div>
<button onClick={this.increment}> Increment </button>
<button onClick={this.decrement}> Decrement </button>
{this.state.counter}
<button onClick={this.onEventHandler}> {this.state.isToggle ? 'Hi':'Ajay'} </button>
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('root'),
);
</script>
</body>
</html>
this.state = {_x000D_
name: "",_x000D_
email: ""_x000D_
}_x000D_
_x000D_
_x000D_
_x000D_
this.setState(() => ({ _x000D_
comments: comments //comments not available in state_x000D_
}))
_x000D_
2.Check the (this) if you doing setState inside any function (i.e handleChange) check whether the function bind to this or the function should be arrow function .
## 3 ways for binding this to the below function##
//3 ways for binding this to the below function_x000D_
_x000D_
handleNameChange(e) { _x000D_
this.setState(() => ({ name }))_x000D_
}_x000D_
_x000D_
// 1.Bind while callling function_x000D_
onChange={this.handleNameChange.bind(this)}_x000D_
_x000D_
_x000D_
//2.make it as arrow function_x000D_
handleNameChange((e)=> { _x000D_
this.setState(() => ({ name }))_x000D_
})_x000D_
_x000D_
//3.Bind in constuctor _x000D_
_x000D_
constructor(props) {_x000D_
super(props)_x000D_
this.state = {_x000D_
name: "",_x000D_
email: ""_x000D_
}_x000D_
this.handleNameChange = this.handleNameChange.bind(this)_x000D_
}
_x000D_
You need to bind this to the constructor and remember that changes to constructor needs restarting the server. Or else, you will end with the same error.
Source: Stackoverflow.com