Búsqueda de sitios web

reactjs - react-query: useQuery devuelve undefined y el componente no se vuelve a renderizar


Estoy jugando con reactQuery en una pequeña aplicación de demostración que puedes ver en este repositorio. La aplicación llama a esta API simulada.

Estoy atascado con un problema en el que estoy usando el hook useQuery para llamar a esta función en un archivo de API de productos:

export const getAllProducts = async (): Promise<Product[]> => {
  const productEndPoint = 'http://localhost:5000/api/product';
  const { data } = await axios.get(productEndPoint);
  return data as Array<Product>;
};

En mi componente ProductTable luego llamo a esta función utilizando:

const { data } = useQuery('products', getAllProducts);

Estoy viendo que la llamada a la API se realiza y se devuelven los datos, pero la tabla en la cuadrícula siempre está vacía.

Si hago depuración, veo que el objeto de datos que devuelve useQuery es indefinido.

La solicitud web se completa con éxito y puedo ver los datos que se devuelven en la pestaña de red bajo solicitudes en el navegador.

Sospecho que es la forma en que está estructurado el getAllProducts o quizás un problema con async await, pero no logro entenderlo del todo.

¿Alguien puede sugerir dónde IO podría estar equivocándose, por favor?

Respuesta #1

Simplemente usa así: al principio, los datos están indefinidos, por lo que mapear datos indefinidos te da un error, así que tenemos que usar isLoading y si isLoading es verdadero, no renderizaremos ni mapearemos los datos hasta entonces, y después de que isLoading se vuelva falso, entonces podemos renderizar o devolver los datos.

export const getAllProducts = async (): Promise<Product[]> => {
  const productEndPoint = 'http://localhost:5000/api/product';
  const res= await axios.get(productEndPoint);
  return res.data as Array<Product>;
};

const { data:products , isLoading } = useQuery('products', getAllProducts);

if(isLoading){
return <FallBackView />
}

return (){
products.map(item => item)
}

Respuesta #2

He logrado hacer que esto funcione. Para beneficio de otros, compartiré mis aprendizajes:

Hice algunos pequeños cambios empezando con mi función de API. Cambiando la función a lo siguiente:

export const getAllProducts = async (): Promise<Product[]> => {
   const response = await axios.get(`api/product`, {
     headers: {
       Accept: 'application/json',
       'Content-Type': 'application/json',
     },
 });

  return response.data as Product[];
};

No descompongo la respuesta de la llamada axios, sino que tomo el objeto data de ella y lo devuelvo como un Product[]

Luego, lo segundo que cambié fue en mi componente ProductTable. Aquí le dije a useQuery qué tipo de respuesta esperar cambiando la llamada a :

const { data } = useQuery<Product[], Error>('products', getAllProducts);

Por último, un error de novato por mi parte: debido a que estaba usando una API simulada en un contenedor de Docker ejecutándose en localhost y llamándola usando http://localhost:5000/api/product, estaba recibiendo el conocido error de red:

localhost ha sido bloqueado por la política CORS: No hay ninguna cabecera 'Access-Control-Allow-Origin' presente...

Así que, para evitar eso con el propósito de este ejercicio, simplemente añadí una propiedad al archivo packages.json: "proxy":"http://localhost:5000",

Esto ahora ha permitido obtener los datos con éxito tal como lo esperaba.

Artículos relacionados