Estoy aprendiendo React y he seguido un tutorial hasta el punto de crear algunos componentes, pasar accesorios, configurar el estado y consultar una API con useEffect(), momento en el que quería intentar construir algo con lo que sé hasta ahora.
Aquí está mi componente de aplicación:
import './App.css'; import CoinList from './components/CoinList/CoinList'; import { useState, useEffect } from 'react'; const heldCoins = ['bitcoin', 'ethereum', 'terra-luna'] const [coins, setCoins] = useState(null) async function getCoinData(coinArray) { let myCoins = [] // think should use map to create this array for await (let coin of coinArray) { fetch(`https://api.coingecko.com/api/v3/coins/${coin}`) .then(res => res.json()) .then(data => { const coinData = { coinName: data.id, price: data.market_data.current_price.gbp } myCoins.push(coinData) }) } return myCoins } useEffect(() => { getCoinData(heldCoins).then(data => setCoins(data)) }, []) return ( <> {coins && <CoinList type="holding" coins={coins} />} </> ) } export default App;Me doy cuenta de que es un poco complicado con async y .then() en uso y probablemente debería estar usando map para crear la nueva matriz, pero siento que esto debería funcionar...
getCoinData es una promesa que devuelve una matriz de objetos de datos. Una vez devuelto, se usa para actualizar el estado con setCoins, dentro del gancho useEffect. Espero que esto active una nueva representación y que los datos estén disponibles para el componente CoinList.
Sin embargo, la matriz vacía se pasa a CoinList antes de que se devuelvan los datos de API.
El mismo proceso está funcionando en el código a lo largo y no puedo identificar dónde me equivoco.
use prometer todo, para iniciar solicitudes paralelas
async function getCoinData(coinArray) { const prms = coinArray.map((coin) => fetch(`https://api.coingecko.com/api/v3/coins/${coin}`) .then((res) => res.json()) .then((data) => { const coinData = { coinName: data.id, price: data.market_data.current_price.gbp, }; return coinData; }) ); return Promise.all(prms); }Soy bastante escéptico sobre lo que hay dentro de su función getCoinData .
async function getCoinData(coinArray) { let myCoins = []; for await (let coin of coinArray) { // here coinArray is not an async iterable, so there's almost no wait happening here fetch(/*some api/) .then(/*some code*/) .then(data => { // some code myCoins.push(coinData) }) } return myCoins // I don't see how this waits for the fetch to finish } Si lee los comentarios que agregué en el fragmento de código anterior, puede ver que su devolución se está realizando mucho antes de que finalice la fetch , por lo que obtiene una devolución vacía si no me equivoco.
Idealmente, podría usar un Promise.all en lugar del desordenado for-await-of , así,
async function getCoinData(coinArray) { const promisesArray = coinArray.map((coin) => fetch(`https://api.coingecko.com/api/v3/coins/${coin}`) .then((res) => res.json()) .then((data) => { const coinData = { coinName: data.id, price: data.market_data.current_price.gbp, }; return coinData; }); ); await Promise.all(promisesArray); return coinData; } Al hacerlo, está esperando efectivamente que cada fetch termine de ejecutarse en lugar de simplemente regresar de inmediato.