【问题标题】:Want to set a state object within a for loop: React+Typescript想要在 for 循环中设置状态对象:React+Typescript
【发布时间】:2019-05-12 18:21:27
【问题描述】:

我有一个状态对象,它基本上是一个对象数组。我正在做一个 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

 }

【问题讨论】:

  • 首先在循环中准备数组,然后只执行一次 setState。像这样:let arr = []; for(let i=0;i&lt;useraccounts.length;i++) { account = { firstname:useraccounts[i].firstname, lastname:useraccounts[i].lastname, age:useraccounts[i].age,id:useraccounts[i].id }; arr.push(account); } this.setState((prevState) =&gt; ({ accounts: [ ...prevState.accounts, arr ]}));

标签: reactjs typescript setstate


【解决方案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 函数违反了Promise 规则之一,其中没有任何东西可以处理它返回的promise:您需要处理发生的任何错误,而不是忽略它们。这就是为什么我添加了try/catch
  • 如果您正在使用for(let i=0;i&lt;useraccounts.length;i++),则无需先使用if(useraccounts.length &gt; 0)。如果没有帐户,您的循环体将不会运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-18
    • 2013-03-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 2021-02-27
    相关资源
    最近更新 更多