En primer lugar, hice una caja de arena: https://codesandbox.io/s/naughty-almeida-u66mlt?file=/src/App.js
El problema es que la imagen solicitada no se muestra cuando se llama a la función y se devuelve la URL.
Lo que he probado hasta ahora y el resultado:
Primero agregué getDownloadURL() dentro de querySnapshot.forEach y empujé la URL recuperada a la matriz de rutas. Se veía así:
useEffect(() => { const q = query(collection(db, "gallery")); const unsubscribe = onSnapshot(q, (querySnapshot) => { const path = []; querySnapshot.forEach((doc) => { getDownloadURL(ref(storage, doc.data().bild)).then((url) { path.push(doc.data(), url); }) }); console.log(path); setPaths(path); }); setLoading(false); return unsubscribe; }, []);Luego mapeé las rutas pero la imagen no se mostró.
Creé otro useState y llamé a la función getURL(src) dentro querySnapshot.forEach() . Dentro de la función getURL() actualicé ese estado con la URL recuperada de getDownloadURL() . Luego agregué el estado a src y funcionó.
Pero mi preocupación es que, cuando hay más de una imagen que falla, aún no la he probado.
Convertí el formulario de URL recuperado getDownloadURL en una cadena. Al igual que
function getURL(src) {...} return String(url) pero eso tampoco funcionó.
El <img /> se representa con el texto "alt", por lo que creo que tiene algo que ver con la URL.
No entiendo el problema en general y espero que alguien pueda ayudarme a solucionarlo.
Puede dividir su componente en pequeños. Digamos Gallery y GalleryImage.
GalleryImage tomará src y accesorios de description . Declare una variable de estado imageSrc en este componente. Luego puede hacer su llamada en useEffect (con src en la matriz de dependencias) y luego establecer el estado de imageSrc cuando se complete la llamada. Llamar a setImageSrc activará una nueva representación.
Sandbox actualizado: https://codesandbox.io/s/silly-fire-f84e95
Tanto cargar datos de Firestore como obtener una URL de descarga para una imagen es una operación asincrónica. Está llamando a setPaths(path) antes de que haya ocurrido cualquiera de las llamadas a path.push(doc.data(), url) .
Recomiendo ejecutar el código en un depurador o agregar un registro para verificar esto, ya que es clave para comprender cómo lidiar con las API asíncronas.
La solución es siempre la misma: cualquier código que necesite datos que se carguen de forma asincrónica, debe estar dentro de la devolución de llamada que se llama cuando esos datos están disponibles.
Entonces, en su caso, la forma más simple de hacerlo sería:
onSnapshot(q, (querySnapshot) => { const path = []; querySnapshot.forEach((doc) => { getDownloadURL(ref(storage, doc.data().bild)).then((url) { path.push(doc.data(), url); setPaths(path); // 👈 }) }); });Esto establece las rutas cada vez que obtiene una URL de descarga.
Si desea esperar a configurar las rutas hasta que obtenga todas las URL de descarga, puede usar un contador para verificar la cantidad de documentos frente a la cantidad de URL de descarga, o puede usar promesas y Promise.all :
onSnapshot(q, (querySnapshot) => { const promises = querySnapshot.docs.map((doc) => getDownloadURL(ref(storage, doc.data().bild))) Promise.all(promises).then((urls) { setPaths(urls); }) });