Tengo una función que obtiene de una API con cuatro puntos finales; uno que devuelve los datos (de otra API) y otros tres que hacen algún análisis de texto. Primero llamo al primer punto final (/getdata), que devuelve los datos más un atributo de texto limpio. Luego uso el texto limpio para llamar a los otros tres puntos finales.
Mi problema es que las tres llamadas de análisis tardan mucho más en completarse. Quiero obtener los datos, mostrar todos los componentes relacionados solo con los datos (sin análisis), luego de que se completen las otras 3 llamadas (habrá una indicación como una animación de carga en los componentes, etc. si es posible), los componentes relacionados a ellos están poblados.
Lo que tengo:
// this is set through a form const [text, setText] = useState(''); const getData = useCallback(async () => { const url = `https://my-api.com/api/getdata?text=${text}`; console.log(url); const response = await fetch(url); const data = await response.json(); return data; }, [text]); const getOtherData = async (data) => { const newData = []; for (const tweet of data.results) { const url1 = `https://my-api.com/api/getsentiment?text=${tweet.clean_text}`; const url2 = `https://my-api.com/api/getkeywords?text=${tweet.clean_text}`; const url2 = `https://my-api.com/api/gettopics?text=${tweet.clean_text}`; const [sentiment, keywords, topic] = await Promise.all([ await fetch(url1).then((res) => res.json()), await fetch(url2).then((res) => res.json()), await fetch(url3).then((res) => res.json()), ]); tweet['sentiment'] = sentiment.sentiment; tweet['keywords'] = keywords.keywords; tweet['topic'] = topic.topics; newData.push(tweet); } return newData; }; const handleSubmit = async () => { ... setLoading(true); const data = await getData(); // this is the raw data plus cleaned text const newData = await getOtherData(data); setData(newData); setLoading(false); }; Probablemente podría setData después de obtener los datos sin el análisis de texto, pero no estoy seguro de cómo actualizar más tarde los otros componentes con los nuevos datos analizados. Configurar los datos nuevamente haría que todo se actualice/recargue, ¿verdad? Pensé en separar el estado para cada uno; uno con los datos sin procesar (y el texto limpio) solamente, y otro con los resultados del análisis de datos sin procesar + texto. ¿Tiene eso sentido o hay una mejor manera?
Puedes usar useEffect() . P.ej:
(Este ejemplo debe entenderse como una ilustración del principio. Es muy probable que este no sea el enfoque óptimo, o incluso podría no funcionar en absoluto para su caso de uso. Por ejemplo, fallaría si los datos pueden cambiar independientemente de estas llamadas de carga, o por ejemplo, el estado de loading puede ser innecesario si los datos nunca pueden cambiar fuera de estas llamadas de carga. También puede considerar usar dos bloques useEffect() y ganchos personalizados )
useEffect( () => { if( !data && !loading ){ // <-- some condition to check if data is loaded setLoading( true ); getData().then( firstData => { setLoading( false ); setData( firstData ); }); } else if( !data.containsNewData && !loading ) { // <-- some condition to check for new data setLoading( true ); getOtherData( data ).then( newData => { setLoading( false ); setData( newData ); }); } else { // all data is available } }, [ data ]);