Search code examples
javascriptmysqlreactjsfirebase-storageuse-effect

How can I map images in React from firebase storage?


Here I am trying to get productList from MySQL database and for each product object I am assigning new property - imageURL via getImages(). When I log productList to console, there is property imageURL with correct url. Problem is, when I try to map it, it shows nothing. Why?

const storageRef = firebase.storage().ref("/assets")

const [productList, setProductList] = useState([])

useEffect(() => {
    Axios.get("http://localhost:3001/product/get").then((response) => {
        setProductList(response.data)
    })  
}, [])

useEffect(() => {
    getImages(productList)
}, [productList])


const getImages = (array) => {
    array.forEach((item) => {
        storageRef.child(`${item.bannerImage}`).getDownloadURL().then((url) => {
            item.imageURL = url
        })
    })
}

My map function:

{productList.map((val) => {
    return (
        <div key={val.id} className="product">
            <div className="item">
                <h1>Product title: {val.title}</h1>
                <h2>Price: {val.price}</h2>
                <h2>Quantity: {val.quantity}</h2>
                <h2>IMAGE: {val.imageURL}</h2>
            </div>
        </div>
    ) 
})}

Solution

  • Problems:

    1. You are not setting productList back in getImages function. You are just iterating over array.
    2. getDownloadURL is a async function, you should not use it inside loop. The best way to do this is through a recursive function. But you can also do this as below:

    Solution

    Your getImage function

    const getImage = async (bannerImage) => {
         const url = await storageRef.child(bannerImage).getDownloadURL();
         return url;   
    }
    

    then your map function

    {productList.map((val) => {
        return (
            <div key={val.id} className="product">
                <div className="item">
                    <h1>Product title: {val.title}</h1>
                    <h2>Price: {val.price}</h2>
                    <h2>Quantity: {val.quantity}</h2>
                    <h2>IMAGE: {getImage(val.bannerImage)}</h2>
                </div>
            </div>
        ) 
    })}