25
votes

I decided to learn React and started with the official tutorial. All is good until I get to this state of my code:

var CommentBox = React.createClass({
  render: () => {
    return (
      <div className="commentBox">
        <h1> Comments </h1>
        <CommentList />
        <CommentForm />
      </div>
    );
  }
});

var CommentForm = React.createClass({
  render: () => {
    return (
      <div className="commentForm">
        Hello, world! I am a comment form;
      </div>
    );
  }
});

var Comment = React.createClass({
  rawMarkup: () => {
    var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
    return {__html: rawMarkup};
  },

  render: () => {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2> // <--- [[[[[[ ERROR IS HERE ]]]]]]
        <span dangerouslySetInnerHtml={this.rawMarkup} />
      </div>
    );
  }
});

var CommentList = React.createClass({
  render: () => {
    return (
      <div className="commentList">
        <Comment author="Pete Hunt">This is one comment</Comment>
        <Comment author="Jordan Walke">This is *another* comment yo</Comment>
      </div>
    );
  }
});

ReactDOM.render(
  <CommentBox />,
  document.getElementById('content')
);

When I try to run it, I get the following error in devtools:

TypeError: Cannot read property 'props' of undefined

...and the debugger pauses at the marked line (see code). When I mouseover this in {this.props.author}, I get a preview of the object which has the props property and everything...

4
I want to add that I was seeing this error recently due to the React dev tools. Just wanted to throw that out there since this is this is the top Google result. - Donald

4 Answers

34
votes

Use function declaration ( render() {} or render: function {}) instead of arrow function render: () => {}

var Comment = React.createClass({
  rawMarkup() {
    var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
    return {__html: rawMarkup};
  },

  render() {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        <span dangerouslySetInnerHtml={this.rawMarkup} />
      </div>
    );
  }
});

Example

An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous.

9
votes

I had the same error message:

Cannot read property 'props' of undefined

...but from a different cause: when this is called from within a function, javascript can not reach the variable because this is in an outer scope. (Note: I was in ES5)

In this case, simply store this in another variable, prior to the function (in the scope of your component): var that = this;

Then you will be able to call that.props from within the function.

Hope this helps for other people who had that error message.

Detailed example below:

render: function() {
  var steps = [];
  var that = this;  // store the reference for later use
  var count = 0;
  this.props.steps.forEach(function(step) {
      steps.push(<Step myFunction={function(){that.props.anotherFunction(count)}}/>);  // here you are
      count += 1;
  });
  return (
    <div>{steps}</div>
  )
}
3
votes

A little late post/answer.

Try to bind your function inside the constructor

example:

this.yourfunction = this.yourfunction.bind(this);
1
votes

I am on ES6 and the arrow function did the trick: rawMarkup = () => {}