Хотите установить объект состояния внутри цикла for: React + Typescript - PullRequest
0 голосов
/ 12 мая 2019

У меня есть объект состояния, который в основном представляет собой массив объектов. Я делаю вызов извлечения, и массив возвращаемых им объектов должен быть установлен в объект состояния. Но я не могу сделать то же самое. Любая альтернатива? Куда я иду не так?

Помощь будет оценена

 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 Ответ

1 голос
/ 12 мая 2019

Вам не нужно вызывать 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).Ваше тело цикла не будет работать, если нет учетных записей.
...