I have a state object which is basically an array of objects. I am doing a fetch call, and the array of objects returned by it should be set to the state object. But It I am unable to do the same. Any alternative? Where am I going wrong?
Help would be appreciated
this.state = {
accounts: [{firstname:"",lastname:"",age:"",id:""}],
};
async componentDidMount(){
let useraccounts = await this.fetchAccounts();
if(useraccounts.length > 0)
{
for(let i=0;i<useraccounts.length;i++)
{
account = {firstname:useraccounts[i].firstname,lastname:useraccounts[i].lastname,age:useraccounts[i].age,id:useraccounts[i].id};
this.setState((prevState) => ({ accounts: [ ...prevState.accounts, account ]}));
}
}
}
fetchAccounts = async() => {
//fetch API call which will return all users accounts
}
You don't need to call setState
for each account individually, just do a single call with all of the accounts:
async componentDidMount(){
try {
let useraccounts = await this.fetchAccounts();
let newAccounts = useraccounts.map(({firstname, lastname, age, id}) => ({firstname, lastname, age, id}));
this.setState(({accounts}) => ({accounts: [...accounts, ...newAccounts]}));
} catch (e) {
// Do something with the error
}
}
That gets the accounts, creates a new array with just the relevant properties (what you were doing in your for
loop), then calls setState
to add the new accounts.
Note that I'm doing destructuring in the parameter lists of the map
callback and the setState
callback to pick out only the parts of the objects they receive that I want. For instance, this:
let newAccounts = useraccounts.map(({firstname, lastname, age, id}) => ({firstname, lastname, age, id}));
is the same as this:
let newAccounts = useraccounts.map(account => {
return {
firstname: account.firstname,
lastname: account.lastname,
age: account.age,
id: account.id
};
});
It's just a bit more concise.
Of course, if you don't really need to copy the objects, you could just use the accounts you got from fetchAccounts
directly:
async componentDidMount(){
try {
let useraccounts = await this.fetchAccounts();
this.setState(({accounts}) => ({accounts: [...accounts, ...useraccounts]}));
} catch (e) {
// Do something with the error
}
}
Some notes on your original code:
async
function where nothing is going to handle the promise it returns: You need to handle any errors that occur, rather than ignoring them. That's why I added a try
/catch
.for(let i=0;i<useraccounts.length;i++)
, there's no need for if(useraccounts.length > 0)
first. Your loop body won't run if there are no accounts.