javascriptreactjsreduxgoogle-cloud-firestoreredux-firestore

Mapping through a fetched array from firebase but nothing shows up even though the array is not empty


I fetched an array of products from firebase with the normal way :

export const getUsersProducts = async uid => {
    const UsersProducts = []
    await db.collection('products').where("userID", "==", uid).get().then(snapshot => {
        snapshot.forEach(doc => UsersProducts.push(doc.data()))
    })
    return UsersProducts
}

and the fetched array shows up in the dom normally, but when I tried to fetch it with onSnapshot method it didnt show up on the DOM even though in appeared in my redux store and when I console log it, it shows up normally.

export const getUsersProducts = uid => {
    let UsersProducts = []
    db.collection('products').where("userID", "==", uid).onSnapshot(querySnapshot => {
        querySnapshot.docChanges().forEach(change => {
            if (change.type === "added") {
                UsersProducts.push(change.doc.data())
            }
        })
    })
    return UsersProducts
}

here is the code used to show it in the DOM

const MyProducts = () => {
    const CurrentUserInfos = useSelector(state => state.userReducer.currentUserInfos)
    const searchQuery = useSelector(state => state.productsReducer.searchQuery)
    const myProducts = useSelector(state => state.productsReducer.usersProducts)
    const dispatch = useDispatch()
    const settingUsersProductList = async () => {
        try {
        const usersProducts = getUsersProducts(CurrentUserInfos.userID)
        dispatch(setUsersProducts(usersProducts))
        console.log(myProducts)
        } catch (err) {
            console.log(err)
        }
    }
    useEffect(() => {
        settingUsersProductList()
    }, [CurrentUserInfos])
    return (
        <div className="my-products">
            <div className="my-products__search-bar">
                <SearchBar />
            </div>
            <div className="my-products__list">
                {
                    Object.keys(myProducts).length===0 ? (<Loading />) : (myProducts.filter(product => {
                        if(searchQuery==="")
                            return product
                        else if(product.title && product.title.toLowerCase().includes(searchQuery.toLowerCase())) 
                            return product
                    }).map(product => {
                        return(
                            <ProductItem
                                key={product.id}
                                product={product}
                            />
                        )
                    }))
                }
            </div>
        </div>
    )
}

export default MyProducts


Solution

  • You are returning the array before promise is resolved hence its empty. Try this:

    export const getUsersProducts = async uid => {
        const snapshot = await db.collection('products').where("userID", "==", uid).get()
        const UsersProducts = snapshot.docs.map(doc => doc.data())
        return UsersProducts
    }
    

    For onSnapshot, add the return statement inside of onSnapshot,

    export const getUsersProducts = uid => {
        let UsersProducts = []
        return db.collection('products').where("userID", "==", uid).onSnapshot(querySnapshot => {
            querySnapshot.docChanges().forEach(change => {
                if (change.type === "added") {
                    UsersProducts.push(change.doc.data())
                }
            })
            return UsersProducts 
        })
    }