React上传文件去重后删除文件无法重新上传同名文件的问题咨询
问题:文件删除后无法重新上传同名文件
我在文件上传功能中使用lodash的cloneDeep方法实现了禁止上传相同文件的逻辑,但上传文件后删除部分文件时,该文件名称仍保留在fileNames状态中,导致无法重新上传同名文件。请问如何在删除文件时将其从状态中一并移除?
const [files, setFiles] = useState([]); //state to store uploaded file's name const [fileNames, setFileNames] = useState([]); const onSelectFile = (e) => { try { let fileArr = cloneDeep(files); let promises = []; for (let file of e.target.files) { promises.push( new Promise((resolve, reject) => { const fileName = file.name //if the file has not been already uploaded if (!fileNames.includes(fileName)) { //add the current fileName in state setFileNames([fileName, ...fileNames]); const type = file.type; let reader = new FileReader(); reader.readAsArrayBuffer(file); reader.onload = function (evt) { const fileData = evt.target.result; fileArr.push({ name: fileName, type: type, data: fileData, comment: "", id: `${new Date().getTime()}_${fileName}`, canDelete: true }); if (typeof props.onFileSelected == "function") props.onFileSelected(fileArr); resolve(true); } reader.onerror = function (evt) { console.log("error reading file"); reject(false); } } else { alert("File has already been uploaded"); reject(false); } }) ); } Promise.all(promises).then(r => { setFiles(fileArr); }) } catch(e) { console.log(e); } }
解决方案
1. 实现同步更新fileNames的删除函数
当删除文件时,需同时更新files和fileNames两个状态,确保被删除文件的名称从状态中移除:
const handleDeleteFile = (fileId) => { // 定位要删除的文件对象 const targetFile = files.find(file => file.id === fileId); if (!targetFile) return; // 过滤移除目标文件,更新files状态 setFiles(prevFiles => prevFiles.filter(file => file.id !== fileId)); // 移除对应文件名,更新fileNames状态 setFileNames(prevNames => prevNames.filter(name => name !== targetFile.name)); }
2. 修复onSelectFile中setFileNames的异步更新问题
原代码在循环中直接调用setFileNames([fileName, ...fileNames]),由于React状态更新是异步的,后续更新会基于旧的状态值,可能导致最终fileNames数组只保留最后一个添加的文件名。改用函数式更新确保基于最新状态:
// 替换原代码中的setFileNames([fileName, ...fileNames]); setFileNames(prevNames => [fileName, ...prevNames]);
3. 可选:优化文件唯一性判断逻辑
如果业务允许同名但内容不同的文件上传,可以结合文件的lastModified和name作为唯一标识,替换仅靠文件名的判断逻辑:
// 生成文件唯一标识 const getFileKey = (file) => `${file.name}_${file.lastModified}`; // 在onSelectFile中替换原有的文件名判断 const fileKey = getFileKey(file); if (!fileKeys.includes(fileKey)) { // 更新fileKeys状态而非fileNames setFileKeys(prevKeys => [fileKey, ...prevKeys]); // ...后续逻辑 }
内容的提问来源于stack exchange,提问作者Alisa
相关产品推荐
相关产品推荐

