我试图不将所有代码都写在同一个文件中,并提取常用功能,例如从Firebase下载图像到单独的功能/文件中。
我在React中有两个函数名为
OfferCard
(从Firebase存储获取图像的下载URL,以将图像提供给OfferCard组件)。我正在尝试从getImage
获取图像文件,并在getImage
功能组件返回的<CardMedia />
图像属性中显示该图像。
我面临的问题是OfferCard
的getImage 无法获取数据并及时返回。表示状态变量setOfferImage
仍为offerImage
或null
。
在控制台中,我可以看到undefined
是控制台记录值 AFTER 后,getImage
控制台记录了值/。
我认为这是异步代码和承诺的问题,但不太确定如何解决这一问题。
OfferCard.js:
OfferCard
获取图片:
import getImage from '../utils/helperFunctions/getImage';
export default function OfferCard(props) {
const classes = useStyles();
const [offerImage, setOfferImage] = React.useState(null)
useEffect(() => {
if (props.image) {
initFirebase();
setOfferImage(getImage(props.image));
console.log(offerImage)
}
}, [])
return (
<Link href={`/offers/${props.id}`}>
<Card className={classes.card} >
{offerImage ?
<CardMedia
image={offerImage}
/> : <CircularProgress/>
}
</Card>
</Link>
)
}
答案 0 :(得分:1)
useEffect(() => {
const fetchImg = async () => {
const res = await getImage(props.image)
setOfferImage(res);
// `setOfferImage` is async
// `console.log(offerImage)` there will be console previous value of `offerImage`
}
if (props.image) {
initFirebase();
fetchImg()
}
}, [props.image])
答案 1 :(得分:1)
此问题是您的getImage
函数实际上是一个void函数,因为它会到达代码的末尾而没有任何返回,因为return(url)
是在第二时刻执行的。
解决方案是使该函数异步,并返回Promise:
export default async function getImage(path) {
let storage = firebase.storage();
let pathReference = storage.ref(`${path}.png`);
return new Promise((resolve, reject) => {
pathReference.getDownloadURL()
.then((url) => {
console.log("returning", url);
resolve(url);
})
.catch((error) => {
// Handle any errors
reject(error)
console.log("Could not get image: ", error);
});
})
}
这样您就可以在useEffect中等待它。请注意,您实际上无法在useEffect(learn more)中等待,因此OfferCard.js将变为
useEffect(() => {
const getImageAsync = async () => {
const url = await getImage(props.image)
if (url)
setOfferImage(url)
else {
// handle error
}
}
if (props.image) {
initFirebase();
getImageAsync();
}
}, [])