2
votes

I am trying to update the state by making api call in componentDidMount phase .

I need to do is to display the name of users . Few names are set in initial state which are working fine . Then i need to append more users which is returned by hitting a get api .

Pseudo code:

export class UserDetails extends Component {
constructor(props) {
    super(props);
    this.state = {
        users: [
            {
              id: 1,
              name: "aditya"
            }
        ]
    };
}
componentDidMount() {
    this.jsonList();
}

jsonList() {
    axios('https://api.myjson.com/bins/1fwkrw').then(function(response) {
        this.setState((prevState) => {
            {users: users.push(response.data.userdata)};
        });
    })
}

render() {
    return (
        <div className="users">
            {this.state.users.map(user => {
              return (
                <div>
                  <div key={user.id}>{user.name}</div>
                </div>
              )
            })}
        </div>
    );
}
}

But here i am getting error "Unhandled Rejection (TypeError): Cannot read property 'setState' of undefined" . Any help where i am going wrong ?

3

3 Answers

4
votes

Either change jsonList to an arrow function:

jsonList = () => {
    axios('https://api.myjson.com/bins/1fwkrw').then(function(response) {
        this.setState((prevState) => {
            {users: users.push(response.data.userdata)};
        });
    })
}

Or bind the method inside the constructer :

constructor(props) {
    super(props);
    this.state = {
        users: [
            {
              id: 1,
              name: "aditya"
            }
        ]
    };
   this.jsonList = this.jsonList.bind(this);
}

The way you wrote it, jsonList is not binded correctly , therefore - you cannot use this.setState since this is undefined .

1
votes

You need to bind your this in the axios promise and also not mutate the state by using concat instead of push

axios('https://api.myjson.com/bins/1fwkrw').then((response) => {
        this.setState((prevState) => {
            return {users: prevState.users.concat(response.data.userdata)};
        });
    })
1
votes

You have to use es6 arrow for auto binding of this to the synthetic handlers.

jsonList = () => {
axios('https://api.myjson.com/bins/1fwkrw').then(function(response) {
    this.setState((prevState) => {
        {users: users.push(response.data.userdata)};
    });
})
}

Your component will re-render because that's how react use Virtual Dom concept. It will see changes and update only that part of component. It doesn't mean that component will be completely mounted again in DOM. I hope this helps