score:8

Accepted answer

Ah OK, there were some interesting problems in here, but you were so close. The big one, with react you must always return a single top-level element (e.g. a div). So, your variable theList was actually an array of divs. You can't return that directly. But you can return it if it's wrapped in a single parent div.

const mockData = [
	{
  	username: 'bob',
    recent: 'seven',
    alltime: 123,
  },
	{
  	username: 'sally mae',
    recent: 'seven',
    alltime: 133999,
  },
];

var $ = {
	ajax(opt) {
  	setTimeout(() => {
    	opt.success(mockData);
    }, 200);
  }
}

const UserList = React.createClass({
  render: function(){
  	let theList;
    if (this.props.data && this.props.data.length) {
      theList = this.props.data.map(function(user, pos){
        return (
          <div key={user.username} className="row user">
            <div className="col">{pos}</div>
            <div className="col">{user.username}</div>
            <div className="col">{user.recent}</div>
            <div className="col">{user.alltime}</div>
          </div>
        );
      });
    } else {
      theList = <div>There is NO data</div>;
    }
    
    return <div>{theList}</div>;
  }
});

const Leaderboard = React.createClass({
  getInitialState: function(){
    return ({data: [], mode: 0});
  },
  componentDidMount: function(){
    $.ajax({
      url: 'https://someurlthatreturnsjson',
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error('https://someurlthatreturnsjson', status, err.toString());
      }.bind(this)
    });
  },
  render: function(){
    return (
      <div className="leaderboard">
        <UserList data={this.state.data}/>
      </div>
    );
  }
}); 

ReactDOM.render(
  <Leaderboard/>,
  document.getElementById('container')
);
.col {
  width: 200px;
  float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

To explain the fiddle a little bit. Don't worry about the weird looking var $ stuff, I'm just stubbing out jQuery's ajax method so I can return some fake data after 200ms.

Also, for me jsfiddle gives me a 'bad config' message when I run it, but I close the message and the result is there. Don't know what that's about.

score:0

There is a small problem with the if statement:

if(this.props.data !== []){

should be:

if(this.props.data){

this.props.data is null, if the ajax call returns null. alternatively the code could be more elaborate.

const data = this.props.data;
if(data && data.constructor === Array && data.length > 0) {

score:0

Not sure if this is how you want to do it, but it works for me.

edit:

const UserList = React.createClass({
  render: function() {
    if(this.props.data){
      return this.props.data.map(function(user, pos){
        return (
          <li> className="row user">
            <span>{pos}</span>
            <span>{user.username}</span>
            <span>{user.recent}</span>
            <span>{user.alltime}</span>
          </li>
        );
      });
    } else {
      return <li>I don't know anymore</li>;
    }
  }
});

score:0

I encountered this error when I rendered a stateless component and decided to remove the react-root-element (wrapping div) after rendering it with basic dom manipulation.

Conclusion: be aware of this, better don't do it.

score:1

Error can also arise from accessing nested state that doesn't exist:

I lack the reputation to comment, so adding an answer for future assistance -- I ran into this same issue for a different reason. Apparently, the error is triggered from an earlier error throwing off react's internal state, but the error is getting caught somehow. github issue #8091

In my case, I was trying access a property of state that didn't exist after moving the property to redux store:

// original state
state: {
  files: [],
  user: {},
}
// ... within render function:
<h1> Welcome {this.state.user.username} </h1>

I subsequently moved user to redux store and deleted line from state // modified state state: { files: [], } // ... within render function (forgot to modify):

<h1> Welcome {this.state.user.username} </h1>

And this threw the cryptic error. Everything was cleared up by modifying render to call on this.props.user.username.

score:4

return (
  {theList}
)

should just be

return theList

because you are not inside JSX at that point. What you're doing there will be interpreted as

return {
  theList: theList
}

That's ES6 shorthand properties syntax.


Related Query

More Query from same tag