David Johns
David Johns

Reputation: 1734

How to get JSON object to React component?

I created a React App with AXIOS. I need to get some JSON data from back end and change the State with that data. When I get the object and mapping to my state, the state is only setting for the last element of the object. So I can only see the last element in the state. How I can get all the elements to the state?

My API call is as follows

API.post('viewallusers', [], config)
      .then(({ data }) => {
        const allUsers = data.response.AllUsers;
        allUsers
          .map(user => {
            return (
              this.setState({
                data: [
                  createData(
                    user.name,
                    user.id,
                    user.email
                  )
                ]
              })
            )
          })
      })
      .catch((err) => {
        console.log("AXIOS ERROR: ", err);
      })

JSON data:

{response :
  {AllUsers :
    0 : {name: "Amy", id: 1, email: "myEmail1"},
    1 : {name: "Doris", id: 2, email: "myEmail2"},
    2 : {name: "Jase", id: 3, email: "myEmail3"}
  }
}

I expect the the state "data" is to be set as follows:

data : [
  createData("Amy",1,"myEmail1"),
  createData("Doris",2,"myEmail2"),
  createData("Jase",3,"myEmail3")
]

But the actual state after getting the JSON data is

data : [
  createData("Jase",3,"myEmail3")
]

How can I solve this?

Upvotes: 0

Views: 62

Answers (2)

Giorgi Moniava
Giorgi Moniava

Reputation: 28685

It probably happens because setState doesn't do a deep merge. So if you have in state

state = {
    key1: 123,
    key2: {
        test1: 1,
        test2: 2

    }

}

And you do

this.setState({
    key2: {
        test1: 4
    }

})

You will end up with

state = {
    key1: 123,
    key2: {
        test1: 4
    }

} 

You have to do instead:

this.setState((ps) => ({
    key2: {
        ...ps.key2,
        test1: 4
    }

}));

Similar approach works if value for key2 is array. Or alternatively you can first map all the data and then do a setState as suggested in other answer.

Upvotes: 1

Yury Tarabanko
Yury Tarabanko

Reputation: 45106

You need to first map the data then set entire state.

API.post('viewallusers', [], config)
  .then(({ data }) => {
    this.setState({
      data: data.response.AllUsers.map(user => (createData(user.name, user.id, user.email)))
    })
  })

Or use callback version of setState and manually merge state.data (NOT recommended in this particular case)

API.post('viewallusers', [], config)
  .then(({ data }) => {
    data.response.AllUsers.forEach(user => {
      this.setState(prev =>
        ({...prev, data: [prev.data, createData(user.name, user.id, user.email)]})
      )
    })
  })

Upvotes: 1

Related Questions