Denis Yakovenko
Denis Yakovenko

Reputation: 3535

ReactJS. Render data from multiple ajax requests

I need to render the data from multiple ajax requests that are performed in a single method in a separate file.

Here's the ajax method:

const Сonsts = ( () => {
    function _getUsers(usernames) {
        let users = [];
        usernames.forEach( (username) => {
            let u = $.getJSON(`https://api.github.com/users/${username}`)
                     .done( (data) => { u = data; });
            users.push(u);
        });
        return users;
    }
    return {
        getUsers: _getUsers
    }

})();

So, I need the data from the request to be rendered as soon as I get the response from the server.

I need the data to be rendered inside this component:

class Team extends React.Component {

  constructor(props) {
    super(props);
    this.state = this.props.members;
  }

  componentDidMount() {
    this.state.members = this.props.members;
  }

  render () {
    console.log(this.state.members);
    let members = this.state.members.map( (item, index) => {
      console.log(item.responseJSON);
      return (
        <img src={item.avatar_url} key={index} />
      )
    });

    return (
      <div>
        {members}
      </div>
    );
  }
}

I render the component like this:

// $aboutContent is a <div> container.
// Consts.team is the array of github usernames.
React.render(<Team members={Сonsts.getUsers(Сonsts.team)} />, $aboutContent);

but this code gives me Invariant Violation: Team.state: must be set to an object or null and, of course, nothing is rendered.

How can I make my component to be rendered properly even when the ajax request is not yet finished? So, basically, I need the following behavior: the user opens the page; the ajax request is performed and at the same time the <Team /> component is rendered with nothing inside, empty div'; as soon as the ajax request is finished and the valid data is stored in some variable inside the app, the render method should be triggered again and render all the data.

Could you help me with achieving this?

Upvotes: 0

Views: 1345

Answers (1)

J. Mark Stevens
J. Mark Stevens

Reputation: 4945

The console.log will trigger multiple times. First with the empty state.members then when setState happens.

    function _getUsers(usernames) {
            let users = [];
            usernames.forEach( (username) => {
                    let u = $.getJSON(`https://api.github.com/users/${username}`)
                                     .done( (data) => { u = data; });
                    users.push(u);
            });
            return {members: users};
    }

class Team extends React.Component {

    constructor(props) {
        super(props);
        //this.state = this.props.members;
        this.state = {members: []};
    }

    componentWillReceiveProps(nextProps) {
        this.setState(_getUsers(nextProps.team));
    }

    render () {
        console.log(this.state.members);
        let members = this.state.members.map( (item, index) => {
            console.log(item.responseJSON);
            return (
                <img src={item.avatar_url} key={index} />
            )
        });

        return (
            <div>
                {members}
            </div>
        );
    }
}

In the top component.

React.render(<Team team={Сonsts.team} />, $aboutContent);

Upvotes: 1

Related Questions