Bailey
Bailey

Reputation: 143

"Cannot read property 'props' of undefined" React Issue

I'm building an app in React based on this tutorial. Instead of using the updated es2016, I'm using an older way, so I'm having some trouble with the challenges that come. I got this error in the browser: "TypeError: Cannot read property 'props' of undefined". I assume it's pointing to the {this.props.onDelete} part. Here's a snippet of my code for the Notes.jsx component:

var Notes = React.createClass({
render: function () {

return (
  <ul>
    {this.props.notes.map(
      function(note) {
        return (
          <li key={note.id}>
            <Note
              onTheDelete={this.props.onDelete}
              task={note.task} />
          </li>
        );
      }
    )}
  </ul>
);
}
});

And here's a snippet from App.jsx, it's parent:

var App = React.createClass({
  getInitialState: function () {
    return {
      notes: [
        {
          id: uuid.v4(),
          task: 'Learn React'
        },
        {
          id: uuid.v4(),
          task: 'Do laundry'
        }
      ]
    }
  },

  newNote: function () {
    this.setState({
      notes: this.state.notes.concat([{
        id: uuid.v4(),
        task: 'New task'
      }])
    });
  },

  deleteNote: function() {
    return 'hi';
  },

  render: function () {
    var {notes} = this.state;

    return (
      <div>
        <button onClick={this.newNote}>+</button>
        <Notes notes={notes} onDelete={this.deleteNote}/>
      </div>
    );
  }
});

I deleted the actually useful parts from deleteNote to make sure no issues were there. I'm having a difficult time wrapping my head around using "this" and what the binding is doing in the tutorial I mentioned.

Upvotes: 1

Views: 4961

Answers (2)

Alex Young
Alex Young

Reputation: 4039

Dave Newton's answer is entirely correct, but I just wanted to add that if you use ES6 arrow functions then you can avoid having to keep an additional reference to this, as well as removing the return statement and taking advantage of the implicit return syntax.

var Notes = React.createClass({
    render: function () {
        return (
          <ul>
            {this.props.notes.map(
              note => {(
                  <li key={note.id}>
                    <Note
                      onTheDelete={this.props.onDelete}
                      task={note.task} />
                  </li>
                )}
            )}
          </ul>
        );
    }
});

Upvotes: 1

Dave Newton
Dave Newton

Reputation: 160191

this inside the map function isn't the same as this outside of it because of how JS works.

You can save off this.props.onDelete and use it w/o the props reference:

render: function () {
  var onDelete = this.props.onDelete;

  return (
    <ul>
      {this.props.notes.map(
        function(note) {
          return (
            <li key={note.id}>
              <Note
                onTheDelete={onDelete}
                task={note.task} 
              />
            </li>
          );
        }
      )}
    </ul>
  );
}

Unrelated, but I'd move that map function into its own function and avoid the deep nesting.

Upvotes: 6

Related Questions