首先,我从数据库中获取 imgs 列表:
{imgs:
[
{_id: '...',img:'***.png'},
...,
]
}
然后使用 ali-oss-hook 签名 img.src ,结果如下:
{imgs:
[
{_id:'...', img: '***.png', src: 'signatured-http-address'}
...,
]
}
然后,将imgs传递给 PictureList 组件:
<PictureList imgs={images}
PictureList 收到了新的道具,但没有渲染
const PictureList = ({ imgs }) => {
return (
<ul>
{imgs.map((i) => (
<img key={i._id} src={i.src} alt="pic" />
))}
</ul>
);
}
export default PictureList
import React, {useEffect, useState, useRef } from 'react'
import { useAlioss } from '../../hooks/oss-hook'
import PictureList from '../../components/PictureList'
import './style.less'
const Pictures = () => {
const [loading, setLoading] = useState(true)
const [signatured, setSignatured] = useState(false)
const [results, setResults] = useState()
const [images, setImages] = useState([])
const { allowUrl } = useAlioss()
const resultsDoSetRef = useRef(false)
async function getImages() {
try {
const dbResponse = await fetch(
`${process.env.REACT_APP_BACKEND_URL}/upload/images`
);
const resu = await dbResponse.json();
setResults(resu)
resultsDoSetRef.current = true
} catch (e) {
console.log("get images failed")
} finally {
setLoading(false)
console.log("get images done!")
}
}
useEffect(() => {
getImages();
}, [])
async function signatureUrl(raw) {
setSignatured(false)
try {
let tempImgs = []
raw.imgs.forEach((r) => {
allowUrl(r.img).then((res) => {
r.img = res;
tempImgs.push(r)
});
});
setImages(tempImgs);
} catch (e) {
console.log("signature failed",e)
} finally {
setSignatured(true)
console.log("signature done!")
}
}
useEffect(() => {
if (resultsDoSetRef.current) {
resultsDoSetRef.current = false
signatureUrl(results);
}
},[results])
return (
<div className="picture">
{loading ? <h1>Loading</h1> : <PictureList imgs={images} />}
</div>
);
};
export default Pictures
const PictureList = ({ imgs }) => {
return (
<ul>
{imgs.map((i) => (
<img key={i._id} src={i.src} alt="pic" />
))}
</ul>
);
}
export default PictureList
chrome react devTool component shows props
chrome devTool element shows empty PictureList
在 chrome devTool 中反应组件中显示了正确的道具,但是PictureList组件仍然为空<ul></ul>
。
哪一部分错了?
答案 0 :(得分:0)
看看PictureList.js,您将“ imgs”作为该函数的参数,这与您传入的属性不同
<PictureList imgs={images}
此“ imgs”实际上是具有imgs属性的对象,因此您的代码将变为:
const PictureList = ({ imgs }) => {
return (
<ul>
{imgs.imgs.map((i) => (
<img key={i._id} src={i.src} alt="pic" />
))}
</ul>
);
}
export default PictureList
P.S:只是一个建议,通常使用props(或类似描述的东西)作为参数自变量,因此您的代码将如下所示:
const PictureList = ({ props }) => {
return (
<ul>
{props.imgs.map((i) => (
<img key={i._id} src={i.src} alt="pic" />
))}
</ul>
);
}
export default PictureList
答案 1 :(得分:0)
在 Picture --signatureUrl()方法中,raw.imgs.forEach()
返回承诺的束缚,这些承诺无法一次全部解决。
当setImages(tempImgs)
时, useState挂钩中的图像首先接收到一个空数组,然后在出现以下情况时将新图像推入 images 数组raw.imgs.forEach()
返回了承诺解决新的图片项。
因此,我们必须等待所有allowUrl(r.img)
的承诺都得到解决,然后setImages(tempImgs)
。
function signatureUrl(raw) {
const tasks = raw.imgs.map(i => allowUrl(i.img))
Promise.all(tasks).then(values => {
let resultImgs = raw.imgs.map((t, index) => ({ ...t, src: values[index] }));
setImages(resultImgs)
})
}
PS:解决方案确实可以,但是所有分析可能都错了,仅供参考。