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

如何用Axios发送多请求?React学生注册表单多表提交问题

学生注册表单批量插入先修课关联数据解决方案

我正在开发一个React学生注册表单,包含自增主键idStudent、名字、姓氏、学院、先修课等字段,用Formik & Yup做校验。后续要和推荐系统关联,根据先修课和科目成绩推荐毕业设计。

最初尝试用单表存储学生数据,后来改用关联表studentPrerequisites(关联student表的idStd和prerequisites表的idPrerequisite)存储学生选中的多个先修课,避免JSON字段更新麻烦。当前需要解决的问题是:如何用Axios实现学生信息插入后,批量插入多个选中的先修课数据。


前端代码修改方案

当前前端代码未将选中的先修课ID数组传给后端,且循环逻辑无效。调整后直接把ID数组放入请求体,一次发送给后端:

const onSubmit = (values, actions) => {
  Axios.post("http://localhost:3001/registerStudent", {
    faculty: values.faculty,
    firstName: values.firstName,
    lastName: values.lastName,
    phone: values.phone,
    email: values.email,
    password: values.password,
    prereqIds: preId // 直接传递选中的先修课ID数组
  })
  .then(() => {
    console.log("注册成功!");
    actions.resetForm();
  })
  .catch(error => {
    console.error("注册失败:", error);
  });
};

后端代码修改方案

后端需要接收前端传来的ID数组,通过事务保证学生信息和关联数据的一致性(要么都插入成功,要么都回滚),以下提供两种实现方式:

方案1:批量INSERT(高效推荐)

利用SQL的批量插入语法,减少数据库交互次数:

app.post("/registerStudent", (req, res) => {
  const { faculty, firstName, lastName, phone, email, password, prereqIds } = req.body;
  
  // 开启事务
  db.beginTransaction((err) => {
    if (err) {
      console.log(err);
      return res.status(500).send("事务初始化失败");
    }

    // 插入学生基础信息
    db.query(
      "INSERT INTO students (email, password, firstName, lastName, faculty, phone) VALUES (?,?,?,?,?,?)",
      [email, password, firstName, lastName, faculty, phone], // 修正原代码中filiere的拼写错误
      (err, result) => {
        if (err) {
          return db.rollback(() => {
            console.log(err);
            res.status(500).send("学生信息插入失败");
          });
        }

        const idStd = result.insertId;
        // 无选中先修课的情况,直接提交事务
        if (!prereqIds || prereqIds.length === 0) {
          return db.commit((err) => {
            if (err) {
              return db.rollback(() => {
                console.log(err);
                res.status(500).send("事务提交失败");
              });
            }
            res.send("注册成功");
          });
        }

        // 构造批量插入的参数数组
        const insertValues = prereqIds.map(id => [idStd, id]);
        db.query(
          "INSERT INTO studentPrerequisites (idStd, idPrerequisite) VALUES ?",
          [insertValues],
          (err, result) => {
            if (err) {
              return db.rollback(() => {
                console.log(err);
                res.status(500).send("先修课关联数据插入失败");
              });
            }

            // 提交事务
            db.commit((err) => {
              if (err) {
                return db.rollback(() => {
                  console.log(err);
                  res.status(500).send("事务提交失败");
                });
              }
              res.send("注册成功,先修课关联完成");
            });
          }
        );
      }
    );
  });
});

方案2:循环插入(适合小批量场景)

若数据库不支持批量INSERT,可通过Promise处理异步循环:

app.post("/registerStudent", (req, res) => {
  const { faculty, firstName, lastName, phone, email, password, prereqIds } = req.body;
  
  db.beginTransaction((err) => {
    if (err) {
      console.log(err);
      return res.status(500).send("事务初始化失败");
    }

    db.query(
      "INSERT INTO students (email, password, firstName, lastName, faculty, phone) VALUES (?,?,?,?,?,?)",
      [email, password, firstName, lastName, faculty, phone],
      (err, result) => {
        if (err) {
          return db.rollback(() => {
            console.log(err);
            res.status(500).send("学生信息插入失败");
          });
        }

        const idStd = result.insertId;
        if (!prereqIds || prereqIds.length === 0) {
          return db.commit((err) => {
            if (err) {
              return db.rollback(() => {
                console.log(err);
                res.status(500).send("事务提交失败");
              });
            }
            res.send("注册成功");
          });
        }

        // 用Promise.all处理异步插入
        const insertPromises = prereqIds.map(id => {
          return new Promise((resolve, reject) => {
            db.query(
              "INSERT INTO studentPrerequisites (idStd, idPrerequisite) VALUES (?,?)",
              [idStd, id],
              (err, result) => err ? reject(err) : resolve(result)
            );
          });
        });

        Promise.all(insertPromises)
        .then(() => {
          db.commit((err) => {
            if (err) {
              return db.rollback(() => {
                console.log(err);
                res.status(500).send("事务提交失败");
              });
            }
            res.send("注册成功,先修课关联完成");
          });
        })
        .catch(err => {
          db.rollback(() => {
            console.log(err);
            res.status(500).send("先修课关联数据插入失败");
          });
        });
      }
    );
  });
});

关键注意事项

  • 事务必要性:必须通过事务保证数据一致性,避免出现学生信息插入成功但先修课关联失败的情况。
  • 参数校验:后端需额外校验prereqIds的合法性(如是否为数组、ID是否存在于prerequisites表),防止非法数据插入。
  • 前端状态管理:确保preId数组正确获取React Select的选中值,避免传递空数组或无效ID。

内容的提问来源于stack exchange,提问作者Yassel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 12:27:13