Как правильно добавлять данные из цикла fetch в массив. Нет возможности обратится к индексу и длине массива
[
1
const [ ships, setShips ] = useState()
useEffect(()=> {
fetch("https://swapi.dev/api/films/2")
.then(res => res.json())
.then(film => {
const starships = film.starships //Ссылки на данные конкретных объектов
const array = []
starships.forEach(ship => {
fetch(ship)
.then(res => res.json())
.then(data => {
array[array.length] = data
})
})
console.log(array)
setShips(array)
})
}, [])
Ответы (2 шт):
В данном случае я бы поменял серверный API, чтоб можно было запрашивать подробности starships за раз. Т. к. иначе получается много лишних http запросов.
array[array.length] = data работает не очень, т. к. реакт не узнает, что стейт поменялся.
Если вызывать set* после каждого мелкого запроса, будет наоборот лишний рендеринг.
Можно решить на клиенте через Promise.all:
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
useEffect(()=> {
fetch("https://swapi.dev/api/films/2").then(res => res.json())
.then(film => {
const starships = film.starships //Ссылки на данные конкретных объектов
return Promise.all(starships.map(ship => fetch(ship).then(res => res.json())))
}).then(data=>setShips(data))
}, [])
Поскольку ваш пример кода не самодостаточный, мне трудно проверить решение, так что могу только предположить. Проблема в том, что starships.forEach() обычно не подходит для работы с асинхронным кодом: в вашем варианте он запустит все запросы синхронно и не будет дожидаться их окончания, поэтому дальнейший код будет иметь дело с пустым массивом. Возможно, самый простой способ — использовать цикл в async/await функции, если вам подходит, что запросы будут отсылаться последовательно. Если вам нужно параллельное выполнение запросов с ожиданием конечного результата, тогда стоит рассмотреть Promise.all(), как вам посоветовали в другом ответе.
fetch("https://swapi.dev/api/films/2")
.then(res => res.json())
.then(async (film) => {
const starships = film.starships
const array = []
for (const ship of starships) {
const res = await fetch(ship)
const data = await res.json()
array.push(data)
}
console.log(array)
setShips(array)
})