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

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.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:03:10