Soy nuevo en React y actualmente estoy tratando de encontrar una forma de llamar a una función solo después de que se hayan actualizado dos variables de estado. Estas variables de estado se actualizan después de ejecutar fetch en mi backend, pero la función a la que intento llamar sigue devolviendo un error porque se llama antes de que se hayan configurado las variables. He estado tratando de usar Effect y async, pero siento que me estoy perdiendo algo. Quiero llamar a "calculateRec" después de que coinbasePrices y binancePrices se hayan configurado usando los datos de fetch. ¡Cualquier ayuda sería muy apreciada!
const [coinbasePrices, setCoinbasePrices] = useState([]); const [binancePrices, setBinancePrices] = useState([]); const [recommendations, setRecommendations] = useState({}); useEffect(() => { (async () => { await fetch('http://localhost:8080/prices/coinbase').then(res => res.json()) .then((data) => { setCoinbasePrices(reformatPrices(data)) }) .catch(err => { throw err }); await fetch('http://localhost:8080/prices/binance').then(res => res.json()) .then((data) => { setBinancePrices(reformatPrices(data)) }) .catch(err => { throw err }); setRecommendations(calculateRec(coinbasePrices, binancePrices)); })(); }, []);Use un useEffect separado con una matriz de dependencia como los dos primeros valores de estado.
Actualización: sugerencias basadas (Gracias) actualizadas con un ejemplo de trabajo usando swapi.
const Component = () => { const [people, setPeople] = React.useState({}); const [planets, setPlanets] = React.useState({}); const [data, setData] = React.useState({}); React.useEffect(() => { fetch("https://swapi.dev/api/people/1/") .then(res => res.json()) .then(setPeople) fetch("https://swapi.dev/api/planets/1/") .then((res) => res.json()) .then(setPlanets) }, []); React.useEffect(() => { if (people && planets) { setData({ person: people.name, planet: planets.name}); } }, [people, planets]); return <div>{JSON.stringify(data)}</div> } ReactDOM.render(<Component />, document.getElementById("app")); <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <div id="app"></div>Creo que tienes varios problemas. Primero, decida si está demandando una combinación de promesa o async await . Luego, asegúrese de que sus ganchos estén definidos correctamente. Usaría un gancho asíncrono para cada recuperación y luego un solo useEffect para calcular los valores finales.
Este sería el gancho de búsqueda de uso:
const useFetch = (url, formatter) => { const [loading, setLoading] = useState(false); const [result, setResult] = useState(null); const [error, setError] = useState(null); const execute = async () => { setLoading(true); setResult(null); setError(null); try { const response = await fetch(url); const data = response.json(); const result = formatter ? formatter(data) : data; setResult(result); setLoading(false); } catch (error) { setError(error); setLoading(false); } }); useEffect(() => { execute(); }, [execute]); return { loading, result, error }; };y en base a eso, esta sería su lógica base:
const YourFunctionalComponent = () => { const [recommendations, setRecommendations] = useState({}); const { result: coinbasePrices } = useFetch('http://localhost:8080/prices/coinbase', reformatPrices); const { result: binancePrices } = useFetch('http://localhost:8080/prices/binance', reformatPrices); useEffect(() => { if (coinbasePrices && binancePrices) setRecommendations(calculateRec(coinbasePrices, binancePrices)); }, [coinbasePrices, binancePrices]); return ( // use your recommendations as you wish... ); };Con esto, puede usar los errores de recuperación individuales como desee junto con las cargas para mostrar el indicador de carga si lo desea.