Есть ли способ установить состояние для каждой итерации foreach? - PullRequest
0 голосов
/ 09 января 2019

Я работаю с API в приложении React и пытаюсь заставить вызовы API возвращаться как одно обещание.

Я использую метод Promise.all (), который отлично работает.

Я застрял, пытаясь настроить результаты двух вызовов API на свое собственное имя. Код обещания работает правильно, и я пытаюсь выполнить forEach () или map () для двух наборов данных и сохранить их в состоянии со своим собственным именем.

Я уверен, что есть простое решение, но я слишком долго чесал голову из-за этого!

Я безуспешно пытался искать во всех документах .map и .forEach!

fetchData(){
this.setState({loading: true})
const urls = ['https://api.spacexdata.com/v3/launches/past', 'https://api.spacexdata.com/v3/launches']

let requests = urls.map(url => fetch(url));
Promise.all(requests)
  .then(responses => {
    return responses
  })
  .then(responses => Promise.all(responses.map(r => r.json())))
  .then(launches => launches.forEach(obj => {
    // I need to set both values to state here
  }))
  .then(() => this.setState({loading: false}))
  }

Вызов API возвращает два разных массива. Мне нужно установить оба массива в State отдельно со своим именем. Это возможно?

Ответы [ 3 ]

0 голосов
/ 09 января 2019

Если два массива не будут мешать друг другу в состоянии, есть ли проблема с простым вызовом setState в каждой итерации?

.then(launches => launches.forEach(obj => {
  this.setState({ [obj.name]: obj });
}))

Если вы хотите минимизировать количество обновлений, вы можете создать объект из двух массивов и распространить его в состояние за один вызов:

.then(launches => this.setState({
    ...launches.reduce((obj, launch) => {
        obj[launch.name] = launch
        return obj
    }, {})
}))
0 голосов
/ 09 января 2019

forEach также предоставляет индекс в качестве второго параметра. Не будет ли что-то подобное этой работой?

launches.forEach((obj, idx) => {
  if (idx === 0) {
    this.setState('first name', obj);
  } else if (idx === 1) {
    this.setState('second name', obj);
  }
})

Кроме того, эта часть буквально ничего не делает ..

  .then(responses => {
    return responses
  })

и Promise.all() здесь тоже ничего не делает.

.then(responses => Promise.all(responses.map(r => r.json())))

должно быть

.then(responses => responses.map(r => r.json()))
0 голосов
/ 09 января 2019

Если я правильно понимаю ваш вопрос, лучшим подходом может быть полное отсутствие итерации (т. Е. Использование forEach() и т. Д.). Вместо этого рассмотрим подход, основанный на « деструктурирующем синтаксисе », когда у вас есть известное / фиксированное количество элементов в массиве, которое разрешено из предыдущего обещания.

Вы можете использовать этот синтаксис следующим образом:

/* 
   The destructing syntax here assigns the first and second element of
   the input array to local variables 'responseFromFirstRequest'
   and 'responseFromSecondRequest' 
*/
.then(([responseFromFirstRequest, responseFromSecondRequest]) => {

      // Set different parts of state based on individual responses
      // Not suggesting you do this via two calls to setState() but
      // am doing so to explicitly illustrate the solution

      this.setState({ stateForFirstRequest : responseFromFirstRequest });
      this.setState({ stateForSecondRequest : responseFromSecondRequest });

      return responses
    })

Итак, в вашей существующей логике это будет выглядеть так:

fetchData() {
  this.setState({
    loading: true
  })
  
  const urls = ['https://api.spacexdata.com/v3/launches/past', 'https://api.spacexdata.com/v3/launches']

  const requests = urls.map(url => fetch(url));
  
  Promise.all(requests)
    .then(responses => Promise.all(responses.map(r => r.json())))
    .then(([responseFromFirstRequest, responseFromSecondRequest]) => {
    
      this.setState({ stateForFirstRequest : responseFromFirstRequest });
      this.setState({ stateForSecondRequest : responseFromSecondRequest });
    
      return responses
    })
    .then(() => this.setState({
      loading: false
    }))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...