React中使用Axios上传Cloudinary资源后secure_url存入State数组重复如何解决
问题原因
你使用的DropzoneArea组件的onChange回调返回的files参数是当前已选中的所有文件的完整列表,并非仅本次新增的文件。因此每次添加新图片时,handleFiles会把历史已上传的旧文件和本次新增的文件全部遍历上传,旧文件重复上传后会再次往fileItems中插入重复的url,这就是重复问题的核心诱因。
解决方案
可以通过记录已处理的文件列表,仅上传本次新增的文件解决问题,同时可新增url去重逻辑做双重保险,完整修改代码如下:
1. 修改State定义
// 存储上传后得到的url const [fileItems, setFileItems] = useState([]); // 新增:存储已经处理过的文件,避免重复上传 const [processedFiles, setProcessedFiles] = useState([]);
2. 修改文件上传处理逻辑
const handleFiles = (allFiles) => { // 筛选出本次新增的未处理文件 const newFiles = allFiles.filter(file => !processedFiles.includes(file)); if (newFiles.length === 0) return; // 提前标记新文件为已处理,避免重复触发上传 setProcessedFiles(prev => [...prev, ...newFiles]); newFiles.forEach((file) => { const formData = new FormData(); formData.append("file", file); formData.append("upload_preset", process.env.REACT_APP_UPLOAD_PRESET); Axios.post( `https://api.cloudinary.com/v1_1/${process.env.REACT_APP_CLOUD_NAME}/upload`, formData, { headers: { "X-Requested-With": "XMLHttpRequest" }, } ) .then((res) => { const newUrl = res.data.secure_url; // 新增url去重逻辑,避免特殊场景下的重复插入 setFileItems(prev => { if (prev.includes(newUrl)) return prev; return [...prev, newUrl]; }); }) .catch((err) => { console.log(err.message); }); }); };
3. 同步修改删除逻辑
删除文件时需要同步清理已处理文件列表和url列表:
const handleDeleteFile = (deletedFileIndex) => { setProcessedFiles(prev => prev.filter((_, index) => index !== deletedFileIndex)); setFileItems(prev => prev.filter((_, index) => index !== deletedFileIndex)); };
如果担心文件对象引用判断不准确,也可以给每个文件生成${file.name}-${file.size}-${file.lastModified}格式的唯一标识串,用标识串判断文件是否已处理,兼容性更强。
内容的提问来源于stack exchange,提问作者Alexdev
相关产品推荐
相关产品推荐

