You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:45:52