user908759
user908759

Reputation: 1355

React Displaying List of Items from Ajax request

I am learning React and I am trying to display a list of users from and ajax call. I am getting an unexpected token error from CodePen when I add the line

export default Users;

When I remove the line there are no more errors but the list of users is not being displayed.

My code:

function GetUsers(project){
  $.ajax({
        url: "https://jsonplaceholder.typicode.com/users",
        success: function (data) {
            console.log(data);
            callback(null, data);
        },
        error: function (error) {
            console.log(data);
            callback(error, {});
        }
    });
}

function UserList(users) {
  const userItems = users.map((user) =>
  <ul>
    <li>
       { user.name }
    </li>
    <li>
      { user.email }
    </li>
    <li>
      { user.phone}
    </li>
  </ul>
 );


 return (userItems);  
}

class Users extends Component {

  componentDidMount() {
    GetUsers(null, function (err, data) {
      if (err)
      {
        console.log(err); 
      }// do something
      this.setState({ users: data })
    }.bind(this))
  }

  render() {
    return(
        <UserList user = {this.state.users} />
      );
  }

}


if (document.getElementById('root')) {
    ReactDOM.render(<Users />, document.getElementById('root'));
}

Here is my code.

Thank you for any and all help!

Upvotes: 0

Views: 89

Answers (2)

Milos Mosovsky
Milos Mosovsky

Reputation: 2983

Problem 1 in AJAX call

function GetUsers(project){
  $.ajax({
        url: "https://jsonplaceholder.typicode.com/users",
        success: function (data) {
            console.log(data);
            callback(null, data);
        },
        error: function (error) {
            console.log(data);
            callback(error, {});
        }
    });
}

$.ajax is asynchronous call, that means it doesn't returns directly any value (how it could if it is fetching the results from the internet) it Just creates another function which will call success and error when completed.

That's why we need to wrap it with callbacks

function GetUsers(project, resolve = () => {}, reject = () => {}) {
}

Problem 2 in mount

  componentDidMount() {
    GetUsers(null, function (err, data) {
      if (err)
      {
        console.log(err); 
      }// do something
      this.setState({ users: data })
    }.bind(this))
  }

This code is completely wrong, it has even syntax error so not worth to discuss it in details.

We need to call our new function and pass success callback for mutating the state

GetUsers(null, users => {
  this.setState({ users });
});

In this way we will call GetUsers wait for it's results and only after that we will mutate the state with new result

3 problem in component creation

React component's don't have state by default, you need to infer the state from constructor so we need to change initialization to

  constructor(props) {
    super(props);

    this.state = {
      users: false
    };
  }

otherwise you will get Cannot call setState of undefined as state is not automatically created for performance purposes and all components are Pure by default.

I have created a working sandbox here

Edit m78ryj51zy

Upvotes: 2

Tyler Sebastian
Tyler Sebastian

Reputation: 9448

in

function GetUsers(project){
  $.ajax({
        url: "https://jsonplaceholder.typicode.com/users",
        success: function (data) {
            return data;
        },
        error: function (error) {
            console.log(error);
            return {};
        }
    });
}

--

success: function (data) {
    return data;
}

doesn't do what you think it does. return data isn't really returning the data... anywhere.

You need to have a callback.

function GetUsers(project, callback){
  $.ajax({
        url: "https://jsonplaceholder.typicode.com/users",
        success: function (data) {
            callback(null, data)
        },
        error: function (error) {
            callback(error, {})
        }
    });
}

class Users extends Component {
  componentDidMount() {
    GetUsers(null, function (err, data) {
      if (err) // do something
      this.setState({ users: data })
    }.bind(this))
  }

  render() {
    return(
      <UserList user = {this.state.users} />
    );
  }
}

you can also Promise-ify things to simplify the logic

Upvotes: 0

Related Questions