要在for循环中设置状态对象:React + Typescript

时间:2019-05-12 18:21:28

标签: reactjs typescript setstate

我有一个状态对象,基本上是一个对象数组。我正在执行fetch调用,并且它返回的对象数组应设置为state对象。但是我无法做到这一点。 还有其他选择吗? 我要去哪里错了?

我们将不胜感激

 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

 }

1 个答案:

答案 0 :(得分:1)

您无需为每个帐户分别呼叫setState,只需对所有帐户进行一次呼叫即可:

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
  }
}

这将获得帐户,创建一个仅具有相关属性(在for循环中所做的工作)的新数组,然后调用setState以添加新帐户。

请注意,我正在map回调和setState回调的参数列表中进行结构分解,以仅挑选出他们想要的对象部分。例如,这:

let newAccounts = useraccounts.map(({firstname, lastname, age, id}) => ({firstname, lastname, age, id}));

与此相同:

let newAccounts = useraccounts.map(account => {
  return {
    firstname: account.firstname,
    lastname: account.lastname,
    age: account.age,
    id: account.id
  };
});

简洁一点。

当然,如果您真的不需要复制对象,则可以直接使用从fetchAccounts获得的帐户:

async componentDidMount(){
  try {
    let useraccounts =  await this.fetchAccounts();
    this.setState(({accounts}) => ({accounts: [...accounts, ...useraccounts]}));
  } catch (e) {
    // Do something with the error
  }
}

关于原始代码的一些注释:

  • 通过使用async函数违反了承诺规则之一,其中什么都无法处理它返回的承诺:您需要处理所有发生的错误,而不是忽略它们。因此,我添加了try / catch
  • 如果您要进行for(let i=0;i<useraccounts.length;i++),则无需先进行if(useraccounts.length > 0)。如果没有帐户,则循环主体将无法运行。