Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invariant Violation in React Render OR the proper way to iterate and return in React

I'm running into persistent problems in my React renders.

This code

/** @jsx React.DOM */
var AnswerRows = React.createClass({
  componentDidMount: function() {
  },
  render: function() {
    {this.props.answers.map(function(answer, i) {
      return (
        <div id="answerRow">
          <label className="AnswerText">
            <input type="checkbox" value={answer.id}  />
            {answer.text}
          </label>
        </div>
      );
    }, this)}
  }
});

var QuizTaking = React.createClass({
  componentDidMount: function() {
  },
  render: function() {
    return (
      <div className="card-holder">
        <div className="showQuestionCard x-card host">
          <h3 dangerouslySetInnerHTML={{__html: this.props.question.text}}></h3>
          <div className="answerRows">
            <AnswerRows answers={this.props.question.answers}/>
          </div>
          <div className='submitAnswers'></div>
        </div>
        <div className="paper-shadow-bottom"></div>
      </div>
    )
  }
})

Will give me Invariant Violation: AnswerRows.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object. errors. However, this works every time:

/** @jsx React.DOM */

var TestIndex = React.createClass({

  propTypes: {
  },
  loadTest: function(i) {
    window.location.replace(this.props.tests[i].url.replace(".json", "/take"))
  },

  render: function () {
    return(
      <div className="testTable card-holder">
        <div className="card-contents">
          {this.props.tests.map(function(test, i) {
            return (
              <div className="testTableRow x-card host" key={test.id}>
                <label className="__TITLE">{test.title}
                  <button onClick={this.loadTest.bind(test, i)}  key={i} type="button" className="StartButton paper-button raisedButton">Start this test</button>
                </label>
                <div className="paper-shadow-bottom"></div>
              </div>
            );
          }, this)}
        </div>
      </div>
    )
  }
});

I'd really like to understand what is going on here, and perhaps the 'right' way to do it.

like image 466
Ryanmt Avatar asked Oct 17 '14 17:10

Ryanmt


1 Answers

You cannot return multiple elements (like the array returned by the map function) from the render function. Also, you're missing a return statement. Try this:

var AnswerRows = React.createClass({
  componentDidMount: function() {
  },
  render: function() {
    return (
      <div>
        {this.props.answers.map(function(answer, i) {
          return (
            <div id="answerRow">
              <label className="AnswerText">
                <input type="checkbox" value={answer.id}  />
                {answer.text}
              </label>
            </div>
          );
        }, this)}
      </div>
    );
  }
});
like image 94
Becojo Avatar answered Nov 15 '22 07:11

Becojo