He estado tratando de usar los datos que obtengo de una función Async dentro de otra función que uso para mostrar HTML en un proyecto de reacción. He hecho varios intentos pero nada parece funcionar para mí. Espero que alguno de ustedes me pueda ayudar. Por favor corrígeme si hice algo mal.
También lo probé con un useEffect:
import React, { useState, useEffect } from 'react'; import { getGenres } from './api/functions'; const ParentThatFetches = () => { const [data, updateData] = useState(); useEffect(() => { const getData = async () => { const genres = await getGenres('tv'); updateData(genres); } getData(); }, []); return data && <Screen data={data} /> } const Screen = ({data}) => { console.log({data}); //logs 'data: undefined' to the console return ( <div> <h1 className="text-3xl font-bold underline">H1</h1> </div> ); } export default Screen;
El error que obtengo de esto es: {datos: indefinido}.
La función getGenres que realiza la Solicitud HTTP:
const apiKey = 'key'; const baseUrl = 'https://api.themoviedb.org/3'; export const getGenres = async (type) => { const requestEndpoint = `/genre/${type}/list`; const requestParams = `?api_key=${apiKey}`; const urlToFetch = baseUrl + requestEndpoint + requestParams; try { const response = await fetch(urlToFetch); if(response.ok) { const jsonResponse = await response.json(); const genres = jsonResponse.genres; return genres; } } catch(e) { console.log(e); } }
Quiero usar los datos dentro de mi HTML, por ejemplo, el H1. Una vez más, no he estado haciendo esto durante mucho tiempo, así que corrígeme si me equivoco.
Hay algunos malentendidos conceptuales que quiero abordar en su código.
En React moderno, sus componentes normalmente deberían representar algún tipo de jsx, que es como React representa html. En su primer ejemplo, está utilizando la aplicación para devolver sus géneros a su componente de pantalla, lo cual no necesita hacer.
Si su objetivo es buscar algunos géneros y luego imprimirlos en la pantalla, solo necesita un componente. Dentro de ese componente, usaráEffect para llamar a una función asincrónica que luego esperará los datos de la API y la establecerá en un estado de reacción. Ese estado será entonces lo que puede iterar.
Cuando los géneros se rendericen por primera vez mediante reaccionar en la línea 6, no estarán definidos. Luego, una vez que se recuperan los datos de API, React actualizará el valor de género para que sea su conjunto de géneros, lo que hará que el componente se vuelva a renderizar.
{genres && genres.map((genre)
... en la línea 20 verifica si los géneros están definidos, y solo si lo está, mapeará (como un bucle) a través de los géneros. Al principio, dado que los géneros no están definidos, nada se imprimirá y no se arrojarán errores.Después de que los géneros se establezcan en nuestro enlace useEffect, los géneros ahora serán una matriz y, por lo tanto, podemos recorrerlos.
Aquí hay un ejemplo de trabajo de su código.
import React, { useState, useEffect } from "react"; import { getGenres } from "./api/functions"; function App() { const [genres, setGenres] = useState(); useEffect(() => { async function apiCall() { const apiResponse = await getGenres("tv"); console.log(apiResponse); setGenres(apiResponse); } apiCall(); }, []); return ( <div> <h1 className="text-3xl font-bold underline">H1</h1> {genres && genres.map((genre) => <div key={genre}>{genre}</div>)} </div> ); } export default App;
Debe usar una combinación o useEffect
y useState
Debe usar useEffect
para iniciar la obtención asíncrona, sin iniciarla en cada renderizado. Si se usa una función asíncrona para obtener algunos datos desde fuera del componente, esto se llama 'efecto secundario', así que use useEffect
.
Debe usar useState
para reaccionar a los cambios en estos efectos secundarios, volviendo a renderizar el componente para obtener los datos en el dom.
En el siguiente ejemplo, estoy usando una función asíncrona ficticia getGenres
que devuelve una matriz de géneros.
Aquí hay un ejemplo y un EJEMPLO DE TRABAJO :
const {useState, useEffect} = React; async function getGenres() { var promise = new Promise(function(resolve, reject) { window.setTimeout(function() { resolve( ['genre1', 'genre2']); }); }); return promise; } const Screen = () => { const [genres, setGenres] = useState([]) useEffect( () => { getGenres().then( res => setGenres(res) ) }, [getGenres] ) return ( <ul> { genres.map( i => <li>{i}</li> ) } </ul> ); } const root = ReactDOM.createRoot(document.getElementById('root')) root.render(<Screen/>)