问题描述
在下面的代码中,我从 Firebase Firestore 获取图像。 url 正确返回并推送到 images state
现在的问题是添加了相同的网址(因为 useEffect
很快或很早就运行了?)
因此,在第二个 useEffect
中,我更新了图像数组并使用 ...new Set
轻松轻松地删除了重复项,但问题是 setimages()
也在那里被调用,这是不允许的,因为这创建无限循环。
所以我的问题是,有人能告诉我在哪里以正确的方式将 updated array uniq
设置为 images state
吗?
提前致谢!
const [evtsFiltered,setEvtsFiltered] = useState([])
const [images,setimages] = useState([])
useEffect(() => {
evtsFiltered?.map((item) => {
storageRef
.child(item)
.getDownloadURL()
.then((url) => {
setimages((images) => [...images,url]) // url returns a plain string such as 'http://image-1.png'
})
})
},[evtsFiltered])
useEffect(() => {
let uniq = [...new Set(images)] // Duplicates are removed
setimages(uniq) // Infinite loop problem
},[images])
解决方法
您的代码需要改进:
-
您不需要将
Windows.Resources
与optional-chaining
一起使用,因为它的初始值是一个空数组。 -
evtsFiltered
如果您只是要遍历数组,则不适合使用该方法。您可以将map()
方法与map()
一起使用来获取图片网址。 -
由于
Promise.all()
钩子,无法使用相同的 URL。您的 Firebase 存储中有重复的网址,或者您没有正确更新状态。 -
如果您在第一个
useEffect
挂钩中正确更新useEffect
状态,则不需要第二个images
挂钩。
尝试使用 useEffect
和 Promise.all()
方法更新状态,如下所示:
map()
使用 useEffect(() => {
const arr = evtsFiltered.map((item) => {
return storageRef.child(item).getDownloadURL();
});
Promise.all(arr)
.then(urls => {
setImages(urls);
})
.catch(err => /* handle error */ );
},[evtsFiltered]);
方法,创建一个 Promise 数组,然后您可以使用 map()
方法解析这些承诺。另外,删除第二个 Promise.all()
钩子。
这是因为您尝试更新您收听的状态更新。一种解决方案是创建另一个包含独特图像的状态。
build.bat
另一个在第一个效果中设置独特的图像。
const [evtsFiltered,setEvtsFiltered] = useState([])
const [images,setImages] = useState([])
const [uniqueImages,setUniqueImages] = useState([])
useEffect(() => {
evtsFiltered?.map((item) => {
storageRef
.child(item)
.getDownloadURL()
.then((url) => {
setImages((images) => [...images,url]) // url returns a plain string such as 'http://image-1.png'
})
})
},[evtsFiltered])
useEffect(() => {
let uniq = [...new Set(images)] // Duplicates are removed
setUniqueImages(uniq) // Infinite loop problem
},[images])