# #javascript #mysql #reactjs #firebase-storage #use-effect
Вопрос:
Здесь я пытаюсь получить список продуктов из базы данных MySQL, и для каждого объекта продукта я назначаю новое свойство — ImageUrl с помощью getImages(). Когда я регистрирую список продуктов в консоли, появляется свойство ImageUrl с правильным URL-адресом. Проблема в том, что когда я пытаюсь нанести его на карту, он ничего не показывает. Почему?
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
})
})
}
Моя функция карты:
{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>
)
})}
Ответ №1:
Проблемы:
- Вы не
productList
возвращаетесь кgetImages
работе. Вы просто перебираете массив.getDownloadURL
этоasync
функция, вы не должны использовать ее внутри цикла. Лучший способ сделать это-с помощьюrecursive
функции. Но вы также можете сделать это, как показано ниже:
Решение
Ваша getImage
функция
const getImage = async (bannerImage) => {
const url = await storageRef.child(bannerImage).getDownloadURL();
return url;
}
тогда ваша map
функция
{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>
)
})}
Комментарии:
1. Спасибо! Но теперь он выдает ошибку: Ошибка: Объекты недопустимы в качестве дочернего элемента React (найдено: [обещание объекта]). Если вы хотели отобразить коллекцию дочерних элементов, вместо этого используйте массив. Эта ошибка указывает на setProductList() в useEffect().
2. Хорошо, не могли бы вы, пожалуйста, сказать мне, что такое val.bannerImage, выполнив console.log? Это веревочка или что-то еще!
3. Это [обещание объекта]
4. Обещание {<в ожидании>} <в ожидании> прото : Обещание [[Обещание]]: «выполнено» [[Обещание]]: «<URL к изображению>»
5. И не могли бы вы, пожалуйста, проверить
url
внутреннюю сетку, а также в консоли?
Ответ №2:
Я бы посоветовал вам создать еще один небольшой компонент для рендеринга изображений и обрабатывать асинхронное getDownloadURL
поведение внутри этого компонента
function ProductImage({bannerImage}) {
const [imageUrl, setImageUrl] = useState('')
useEffect(() => {
async function getImage(bannerImage) {
const url = await bannerImage.getDownloadURL()
setImageUrl(url)
}
getImage(bannerImage)
}, [bannerImage])
return imageUrl ? <h2>IMAGE: {imageUrl}</h2> : '...Loading'
}
И используйте этот компонент в своем основном компоненте
{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>
<ProductImage bannerImage={val.bannerImage} />
</div>
</div>
)
})}
Комментарии:
1. Собираюсь попробовать это!