如何解决React Hooks-在另一个函数中通过Promise设置状态变量
我试图不将所有代码都写在同一个文件中,并提取常用功能,例如从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>
)
}
解决方法
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])
,
此问题是您的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();
}
},[])
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。