ReactJS and complex JSON object

14,715

Solution 1

When your component first renders, NotificationStatus's this.state.data will be {} because that's what's returned from getInitialState. That means that when you render

<Notifications data={this.state.data.notificationType} />

you're passing {}.notificationType or undefined:

<Notifications data={undefined} />

So when Notifications first renders, this.props.data isn't a list. It depends on your application what the right fix here is, but perhaps you want to initialize with data: null and add this to the top of NotificationStatus's render method:

if (!this.state.data) {
    return <div>Loading...</div>;
}

Solution 2

In addition to Ben's point, you're also calling loadNotificationsFromServer in componentWillMount. You should call loadNotificationsFromServer and start any timers inside of componentDidMount, as your component has not yet been mounted in the DOM. You can read more here: React Component Lifecycle

Looking back at the code, I'm not entirely sure what your object graph should look like, but in one place it looks like you're trying to iterate over a collection of notifications and in another a single notification.

To alleviate the issue Ben mentioned, you could also initialize your state with default values for notificationType and count ('' and 0) as a quick fix, but the logical operator would work just as well.

Share:
14,715

Related videos on Youtube

Seif Eddine Mouelhi
Author by

Seif Eddine Mouelhi

Updated on September 15, 2022

Comments

  • Seif Eddine Mouelhi
    Seif Eddine Mouelhi over 1 year

    I followed ReactJS tutorial, which is quite simple to accomplish more complex stuff.

    In my case, I would like to use a complex JSON object, which contains a map, a single value, a list, etc... Here is the code:

        var NotificationStatus = React.createClass({
        loadNotificationsFromServer: function() {
          $.ajax({
            url: this.props.url,
            dataType: 'json',
            success: function(data) {
              this.setState({data: data});
              console.log(this.state.data.notificationType);
            }.bind(this)
          });
        },
        getInitialState: function() {
          return {data: {}};
        },
        componentWillMount: function() {
          this.loadNotificationsFromServer();
          setInterval(this.loadNotificationsFromServer, this.props.pollInterval);
        },
        render: function() {
          return (
            <div>
              <li className="dropdown-menu-title">
                  <span>You have {this.state.data.notificationCount} notifications</span>            
              </li>
              <Notifications data={this.state.data.notificationType} />
            </div>  
          );
        }
      });
    
    
    
      var Notifications = React.createClass({
        render: function() {
          var notificationNodes = this.props.data.map(function (notif, index) {
            return <Notification key={index}>{notif.type}</Notification>;
          });
          return <li>{notificationNodes}</li>;
          }
      });
    
      var Notification = React.createClass({
        render: function() {
          return (
            <a href="#">
                  <span className="icon blue"><i className={this.props.children == "user" ? 'icon-user' : 'icon-comment-alt'}></i></span>
                  <span className="message">{this.props.children}</span>           
                  <span className="time">1 min</span>
              </a>
          );
        }
      });
    
      React.renderComponent(
        <NotificationStatus url="/data/notifications.json" pollInterval={2000} />,
        document.getElementById('notificationbar')
      );
    

    And this is a sample from the JSON:

        {
        "notificationCount": "1",
        "notificationType": [
           {
             "type": "update",
             "text": "New Update"
           },
           {
              "type": "user",
              "text": "New User"
           }
         ]
        }
    

    When I try to get notificationType, an error "this.props.data is undefined" is raised at this point

        var notificationNodes = this.props.data.map(function (notif, index) {
    

    I really don't see what's wrong with the declaration, and when I get the JSON at the ajax level, I do have a map (verified with the console.log).

    Any help would be great.

    Thanks a lot.