0
votes

I cannot for the life of me figure out what is wrong with the following code, when a user adds a bug via the BugAdd form, the values are passed to the handleSubmit function which in turn should pass its props to addBug.

However, when I submit my form I see the 'console.log("Adding bug:", bug);'

But then after this I receive "react.min.js:14 Uncaught TypeError: Cannot read property 'bugs' of undefined", my initial thought was that perhaps I have missed a .bind somewhere.

Can anyone spot an issue with my code, it was working fine before refactoring to ES6

class BugAdd extends React.Component {
  render() {
    console.log("Rendering BugAdd");
    return (
      <div>
        <form name="bugAdd">
          <input type="text" name="owner" placeholder="Owner" />
          <input type="text" name="title" placeholder="Title" />
          <button onClick={this.handleSubmit.bind(this)}>Add Bug</button>
        </form>
      </div>
    )
  }

  handleSubmit(e) {
    e.preventDefault();
    var form = document.forms.bugAdd;
    this.props.addBug({owner: form.owner.value, title: form.title.value, status: 'New', priority: 'P1'});
    // clear the form for the next input
    form.owner.value = ""; form.title.value = "";
  }
}

class BugList extends React.Component {

  constructor() {
    super();
    this.state = {
      bugs: bugData
    }
  }

  render() {
    console.log("Rendering bug list, num items:", this.state.bugs.length);
    return (
      <div>
        <h1>Bug Tracker</h1>
        <BugFilter />
        <hr />
        <BugTable bugs={this.state.bugs} />
        <BugAdd addBug={this.addBug} />
      </div>
    )
  }

  addBug(bug) {
      console.log("Adding bug:", bug);
      // We're advised not to modify the state, it's immutable. So, make a copy.
      var bugsModified = this.state.bugs.slice();
      bug.id = this.state.bugs.length + 1;
      bugsModified.push(bug);
      this.setState({bugs: bugsModified});
  }
}
2
You're not binding this.addBug.ivarni
How is out that the addBugs method of the second component finds itself on the slope of the first?Robert Moskal
You might want to post your old working code so we can see your intent.Robert Moskal
@ivarni - man... At least I suspected the right thing even if I couldn't spot it!user4831663
@James When you look at code long enough it's sometimes hard to spot these things. As was suggested in one of the answers you should bind the function in the constructor so it doesn't have to be bound every time the component renders.ivarni

2 Answers

0
votes

When you extend React.Component with ES6 class, the component methods are not autobinded to this like when you use React.createClass. You can read more about this in the official documentation.

In your case, the cleanest solution is to bind the addBug method in the constructor to the component's this, like this:

class BugList extends React.Component {

  constructor() {
    super();
    this.state = {
      bugs: bugData
    }
    this.addBug = this.addBug.bind(this);
  }

  render() {
    console.log("Rendering bug list, num items:", this.state.bugs.length);
    return (
      <div>
        <h1>Bug Tracker</h1>
        <BugFilter />
        <hr />
        <BugTable bugs={this.state.bugs} />
        <BugAdd addBug={this.addBug} />
      </div>
    )
  }

  addBug(bug) {
      console.log("Adding bug:", bug);
      // We're advised not to modify the state, it's immutable. So, make a copy.
      var bugsModified = this.state.bugs.slice();
      bug.id = this.state.bugs.length + 1;
      bugsModified.push(bug);
      this.setState({bugs: bugsModified});
  }
}

Now you will be able to access this.state.

0
votes

try to define your addBug method like this with => which will auto bind to the class instance:

  addBug = (bug) => {
      console.log("Adding bug:", bug);
      // We're advised not to modify the state, it's immutable. So, make a copy.
      var bugsModified = this.state.bugs.slice();
      bug.id = this.state.bugs.length + 1;
      bugsModified.push(bug);
      this.setState({bugs: bugsModified});
  }

don't forget to add the Class properties transform to your babel http://babeljs.io/docs/plugins/transform-class-properties/