如何解决React结合Axios实现多文件上传进度不渲染的问题
React多文件上传进度不渲染问题解决方案
核心根因
没有遵守React的state不可变规则:你直接原地修改files数组中file对象的progress属性,React的浅比对检测不到state的引用变化,因此不会触发组件重渲染,哪怕DevTools能看到属性已经更新。
另外原代码存在语法逻辑错误:FormData的定义被写在了axios的请求配置参数内部,实际无法正常执行上传。
完整修正代码
const [files, setFiles] = useState([]) const saveDocuments = () => { files.forEach((file, index) => { // 先创建FormData,不要嵌套在请求配置里 const formData = new FormData(); formData.append("attached_file", file); formData.append("name", file.name); axios.post("/api/documents", formData, { headers: { "X-CSRFTOKEN": getCookie("csrftoken"), "Content-Type": "multipart/form-data", }, onUploadProgress: (progressEvent) => { const percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); // 必须通过setFiles生成全新的state引用,触发重渲染 setFiles(prevFiles => prevFiles.map((prevFile, i) => // 只更新对应索引的文件,生成新的文件对象 i === index ? { ...prevFile, progress: percentCompleted } : prevFile ) ); }, }).catch(err => { // 异步错误需要单独捕获,外层同步try/catch无效 console.log(err); }); }); };
渲染逻辑无需修改,只要state是全新引用,进度值就可以正常更新展示。
注意事项
- 永远不要原地修改state中的对象、数组,所有state更新都必须返回新的引用,单层属性更新用浅拷贝即可
- 目前渲染用的
key是数组索引,后续如果涉及文件删除、排序操作,建议替换为文件的唯一标识(比如上传前生成的临时ID),避免渲染异常
内容的提问来源于stack exchange,提问作者Aurélien
相关产品推荐
相关产品推荐

