React: Error referencing a function within state

Viewed 81

the problem seems simple, but I can't figure out how to solve it:

  • Add-Button declared within the render-Function works just fine
  • Add-Button declared within the state itself doesn't work. As the code already mentions, it will throw the "TypeError: Cannot read property 'state' of undefined"-Error
class App extends Component {
  constructor() {
    super();

    this.state = {
      someArrayOfObjects: [{
          attr: 
             // SNIP ...
                // Doesn't work!
                // When clicked leads to this error: "TypeError: Cannot read property 'state' of undefined"
                <button onClick={this.doAction}>Add</button>
             // SNIP ...
        }]
    };

    this.doAction = this.doAction.bind(this);
  }

  // SNIP ...
  doAction() {
    console.log(this.state);
  }

  render() {
      return(
          // SNIP...
          // Works just fine
          <button onClick={this.doAction}>Add</button>
      )
  }
}

What am I missing out?

2 Answers

You need to bind the function doAction before the state

constructor() {
    super();

    this.doAction = this.doAction.bind(this);

    this.state = {
      someArrayOfObjects: [{
          attr: 
             // SNIP ...
                // Doesn't work!
                // When clicked leads to this error: "TypeError: Cannot read property 'state' of undefined"
                <button onClick={this.doAction}>Add</button>
             // SNIP ...
        }]
    };

  }

Edit: You need to bind the function before the state creation. At the point at which you are creating the button in the state, this.doAction refers to the prototype method of the component class. But you can't pass a method as a callback directly, so you need to bind it. Function.prototype.bind creates a new function, which you then assign to the instance being created in the constructor:

this.doAction = this.doAction.bind(this);

So, perhaps confusingly, this.doAction refers to two different functions at different points in the code. You want to pass the bound version to the handler (see link above for why), so you need to bind it before creating that button.

Please check the code in sandbox: https://codesandbox.io/s/young-architecture-0r1tk

Here you can see that we need to define the method before adding that into state. As first we need to define doAction method then state,as it is used inside state.

Related