如何用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
相关产品推荐
相关产品推荐

