[javascript] React - uncaught TypeError: Cannot read property 'setState' of undefined

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

The answer is


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:

Javascript ES6 — Arrow Functions and Lexical this


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>

  1. Check state check state whether you create particular property or not

_x000D_
_x000D_
this.state = {_x000D_
            name: "",_x000D_
            email: ""_x000D_
            }_x000D_
            _x000D_
           _x000D_
            _x000D_
this.setState(() => ({ _x000D_
             comments: comments          //comments not available in state_x000D_
             })) 
_x000D_
_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##

_x000D_
_x000D_
//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_
_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.