1
votes

I am working off Alex Bank's "Building a Polling App with Socket IO and React.js" (Lynda.com), but I am trying to upgrade it to react-router 1.0.0-RC1.


My github repository can be found here ....

Problem:

When a speaker signs in and creates a presentation, a list of questions successful appears. However, when the speaker clicks on a respective question to emit to the attendees, I receive the error: "Cannot read property 'props' of null" which identifies the error in the Question.js component:

ask(question) {
  console.log('this question: ' + JSON.stringify(question));
  this.props.emit('ask', question); <--- Console points to this
}

But I do not believe that is the problem per se. I believe the actual problem is that this emit is not reaching the socket.on in the app.

APP.js:

componentWillMount() {
  this.socket = io('http://localhost:3000');
  this.socket.on('ask', this.ask.bind(this));
  ....
}

ask(question) {
  sessionStorage.answer = '';
  this.setState({ currentQuestion: question });
}

I believe it is react-router related, but the parent route does have component {APP}, and Speaker is a child route and the Speaker component does import the Question component, so I am assuming the Question component is connected to the APP's.

In Alex's project it is working, but he uses:

  "react": "^0.13.3",
  "react-router": "^0.13.3", 

Any chance someone can offer me some insight on this?

Many Thanks!

2

2 Answers

5
votes

If your error says "Cannot read property 'props' of null," that's exactly what's happening: you're attemping to call .props on a value that is null.

However, the real problem is in this code:

ask(question) {
  console.log('this question: ' + JSON.stringify(question));
  this.props.emit('ask', question);
}

addQuestion(question, index) {
  return (
    <div key={ index } className="col-xs-12 col-sm-6 col-md-3">
      <span onClick={ this.ask.bind(null, question) }>{ question.q }</span>
    </div>
  );
}

Specifically, this code (which isn't included in the question):

onClick={ this.ask.bind(null, question) }>

You're assigning a click handler to a version of this.ask that's bound to null; this works fine with React.createClass-type components, because React forcibly and automatically binds all component methods to the component instance, no matter what you pass as the first argument to .bind() (and so null is commonly used; I think React actually yells at you otherwise). However, this is not the case with ES6 classes; you're literally setting this inside ask() to null.

A correct version would be

onClick={ this.ask.bind(this, question) }>

or, commonly, as an anonymous function

onClick={ () => this.ask(question) }>
1
votes

The error message indicates this is null. The reason is react doesn't autobind this to the react element. That is, the this doesn't reference to the element itself while invoking ask(question) method. You only have to bind it in the constructor: this.ask = this.ask.bind(this). It's better for you to read the ES6 class notes on official react blog.

Reading react-router upgrade guide is also a good idea :)