React中setListImg无法接收Blob值,useState更新延迟致报错
问题解决思路与代码修复
核心问题分析
- useState异步更新特性:
setListImg是异步操作,调用后listImg不会立刻更新,组件首次渲染时listImg仍为空数组,直接访问listImg[fun.cod-1]会得到undefined,触发URL.createObjectURL报错。 - 索引依赖不可靠:通过
fun.cod-1作为数组索引关联图片,若listFunc顺序变动,会导致图片与对应项不匹配。 - 未处理加载状态:图片加载完成前直接渲染,无 fallback 逻辑,引发报错。
修复后的代码
import { useEffect, useState, useRef } from 'react'; // 组件内部逻辑 const [listImg, setListImg] = useState([]); const [status, setStatus] = useState('carregando'); const urlRefs = useRef({}); // 存储创建的URL,用于后续内存清理 useEffect(() => { if (listFunc.length === 0) return; const imgfetch = async () => { setStatus('carregando'); // 返回包含cod和blob的对象,避免依赖数组索引匹配 const imgFiles = await Promise.all( listFunc.map(async (fun) => { const resp = await fetch(`${url}imagem/${fun.cod}-func`, { method: 'GET' }); const blob = await resp.blob(); return { cod: fun.cod, blob }; }) ); setListImg(imgFiles); setStatus('ocioso'); }; imgfetch(); // 清理内存:组件卸载或listFunc变化时,销毁已创建的URL return () => { Object.values(urlRefs.current).forEach(url => URL.revokeObjectURL(url)); urlRefs.current = {}; }; }, [listFunc, url]); // 补充url到依赖数组,符合React Hooks规则 return ( <div> {status === 'carregando' ? ( <p>Carregando imagens...</p> ) : ( listFunc.map((fun) => { // 通过cod精准匹配对应的blob数据 const imgData = listImg.find(item => item.cod === fun.cod); // 仅当blob存在时才创建URL const imgUrl = imgData?.blob ? URL.createObjectURL(imgData.blob) : null; // 将URL存入ref,方便后续清理 if (imgUrl) urlRefs.current[fun.cod] = imgUrl; return ( <div style={{ textAlign: "justify", padding: '20px 100px 0px 100px' }} key={fun.cod}> <div style={{ display: "flex" }}> {/* 图片加载失败或未就绪时显示占位图 */} <img src={imgUrl || '你的占位图地址'} alt={fun.nome} onError={(e) => e.target.src = '你的占位图地址'} /> <div style={{ paddingLeft: '20px' }}> <h2>{fun.nome}</h2> <p>{fun.desc}</p> </div> </div> <hr /> </div> ) }) )} </div> );
关键改动说明
- 关联cod与Blob:放弃数组索引匹配,改用
cod字段精准关联图片数据,避免顺序变动导致的匹配错误。 - 加载状态处理:添加加载中提示,避免图片未加载完成时直接渲染引发报错。
- 空值安全判断:使用可选链
?.判断blob是否存在,仅在有效时调用URL.createObjectURL。 - 内存泄漏防护:通过
useRef存储创建的URL,在组件卸载或依赖变化时主动释放内存。 - 完善依赖数组:将
url补充到useEffect依赖中,符合React Hooks的规范要求。
内容的提问来源于stack exchange,提问作者João
相关产品推荐
相关产品推荐

