简体   繁体   English

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

[英]Want to set a state object within a for loop: React+Typescript

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. 我正在执行fetch调用,并且它返回的对象数组应设置为state对象。 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: 您不需要分别为每个帐户调用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
  }
}

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. 这样就获得了帐户,创建了一个仅具有相关属性的新数组(您在for循环中所做的for ),然后调用setState添加新帐户。

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. 请注意,我正在对map回调和setState回调的参数列表进行setState以仅选择它们接收到的想要的对象部分。 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: 当然,如果您真的不需要复制对象,则可以直接使用从fetchAccounts获得的帐户:

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: 关于原始代码的一些注意事项:

  • You're breaking one of the rules of promises by using an async function where nothing is going to handle the promise it returns: You need to handle any errors that occur, rather than ignoring them. 您将通过使用async函数来破坏承诺的规则之一,其中没有什么东西将无法处理它返回的承诺:您需要处理所有发生的错误,而不是忽略它们。 That's why I added a try / catch . 这就是为什么我添加了try / catch
  • If you're doing for(let i=0;i<useraccounts.length;i++) , there's no need for if(useraccounts.length > 0) first. 如果您要for(let i=0;i<useraccounts.length;i++) ,则不需要先if(useraccounts.length > 0) Your loop body won't run if there are no accounts. 如果没有帐户,则循环主体将无法运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM