React Redux多文件上传:需全部成功后关模态框/失败提示
解决多文件上传后统一关闭模态框的问题
你的问题核心在于每个文件上传成功后都会单独触发CLOSE_MODAL,导致第一个文件传完就关闭了模态框,完全没等到其他文件处理完成。咱们一步步来修正这个逻辑:
1. 调整组件的上传触发逻辑
首先,不要在组件里循环调用saveFile,而是发起一个批量上传的action,把所有文件一次性传给saga处理:
// ModalUploadFile.jsx uploadFile = () => { this.refs.btn.setAttribute("disabled", "disabled"); // 发起批量上传的action,而不是逐个调用saveFile this.props.uploadAllFiles(this.props.selected_candidate.id, this.state.files); }
2. 修改Saga逻辑,批量处理上传并统一判断结果
接下来在Sagas.js里,新增一个处理批量上传的saga,用all来并行处理所有文件的上传请求,然后统一处理成功/失败的情况:
// Sagas.js // 先保留单个文件上传的saga,但去掉里面的CLOSE_MODAL和错误处理(移到批量saga里) function* saveFile(action) { try { const file = action.file; const formData = new FormData(); formData.append("file", file); const response = yield fetch(URL, { method: "POST", credentials: "same-origin", body: formData }); const result = yield response.json(); // 只返回成功结果,不处理关闭模态框 return { success: true, data: result }; } catch (ex) { // 返回失败信息,包含错误和对应的文件 return { success: false, error: ex, file: action.file }; } } // 新增批量上传的saga function* uploadAllFiles(action) { const { candidateId, files } = action; // 生成所有单个文件上传的任务 const uploadTasks = files.map(file => call(saveFile, { candidateId, file }) ); // 等待所有上传任务完成(不管成功失败) const results = yield all(uploadTasks); // 检查是否有失败的上传 const failedUploads = results.filter(res => !res.success); if (failedUploads.length > 0) { // 有文件上传失败,dispatch错误action,用于组件显示提示 yield put({ type: actionTypes.FILE_UPLOAD_FAILED, errors: failedUploads.map(f => ({ fileName: f.file.name, message: f.error.message || "文件上传失败" })) }); } else { // 所有文件都上传成功,关闭模态框 yield put({ type: actionTypes.CLOSE_MODAL }); // 可以顺便dispatch所有文件上传完成的action,更新状态 yield put({ type: actionTypes.ALL_FILES_UPLOADED, results: results.map(res => res.data) }); } } // 记得在root saga里注册这个新的saga function* rootSaga() { yield takeEvery(actionTypes.UPLOAD_ALL_FILES, uploadAllFiles); // ...其他saga注册 }
3. 组件里添加错误提示逻辑
在ModalUploadFile.jsx里,监听FILE_UPLOAD_FAILED的action(通过connect映射到props),然后显示错误提示:
// 假设是类组件,通过connect获取错误状态 componentDidUpdate(prevProps) { if (this.props.uploadErrors && this.props.uploadErrors.length > 0 && prevProps.uploadErrors !== this.props.uploadErrors) { // 显示错误提示,比如用自定义弹窗或UI库的提示组件 const errorMsg = this.props.uploadErrors.map(err => `${err.fileName}: ${err.message}`).join("\n"); alert(`以下文件上传失败:\n${errorMsg}`); // 重新启用提交按钮 this.refs.btn.removeAttribute("disabled"); } } // connect部分 const mapStateToProps = state => ({ uploadErrors: state.upload.uploadErrors // 假设你的redux state里有这个字段 }); const mapDispatchToProps = dispatch => ({ uploadAllFiles: (candidateId, files) => dispatch({ type: actionTypes.UPLOAD_ALL_FILES, candidateId, files }) }); export default connect(mapStateToProps, mapDispatchToProps)(ModalUploadFile);
关键逻辑说明
- 用
yield all(uploadTasks)可以并行处理所有文件上传,等待所有任务完成后再统一处理结果,避免单个文件完成就触发关闭。 - 单个文件上传的saga返回成功/失败的结果,批量saga收集结果后判断是否有失败,再决定关闭模态框还是提示错误。
- 错误信息包含文件名,方便用户定位问题文件。
这样修改后,就能实现所有文件上传完成后关闭模态框,有失败则提示的需求啦!
内容的提问来源于stack exchange,提问作者Carl V.
相关产品推荐
相关产品推荐

