使用Material UI渲染axios获取的数据时图片无法显示问题求助
问题根因
forEach不支持异步等待,你在forEach中发起的批量获取相册照片的请求都是异步执行的,执行setAlbums(tempArr)时这些请求还没有返回结果,所以此时存入state的数组元素并没有photos属性。你在控制台看到的带photos的数组是因为控制台打印的是对象引用,等你手动点开查看时异步请求已经执行完成,才会显示完整数据,这是前端调试时的常见误区。- useEffect 直接传入async函数属于错误用法,React会把async函数返回的Promise当成清理函数,可能引发额外的问题。
- 冗余操作:
let tempArr = JSON.parse(JSON.stringify(res)).data完全没有必要,axios会自动将接口返回的JSON数据解析为JS对象,直接取res.data即可,多余的序列化反序列化只会带来性能损耗。
修复方案
用Promise.all等待所有照片请求完成后再更新state,修改后的useEffect逻辑如下:
useEffect(() => { // 异步逻辑封装在内部函数中,不要直接给useEffect传async回调 const fetchAlbums = async () => { const res = await axios.get(`https://jsonplaceholder.typicode.com/albums?userId=2`); const tempArr = res.data; // 用Promise.all等待所有相册的照片请求全部完成 const albumWithPhotos = await Promise.all( tempArr.map(async (album) => { const photoRes = await axios.get(`https://jsonplaceholder.typicode.com/albums/${album.id}/photos`); return { ...album, photos: photoRes.data } }) ) // 所有数据准备完成后再更新state setAlbums(albumWithPhotos); } fetchAlbums(); }, []);
渲染逻辑优化
建议使用可选链做防御性判断,避免嵌套属性读取时报错:
{item?.photos?.length && <ButtonBase sx={{ width: 128, height: 128 }}> <Img alt="complex" src={item.photos[0].thumbnailUrl} /> </ButtonBase> }
如果需要访问item.photos[0].thumbnailUrl做其他逻辑,也可以写成item?.photos?.[0]?.thumbnailUrl,哪怕中间某一层属性不存在也不会抛出报错,只会返回undefined。
内容的提问来源于stack exchange,提问作者vimuth
相关产品推荐
相关产品推荐

