React多步骤表单重复提交排查及重置功能求助
问题解决与代码修改
核心问题分析
你当前的代码里,所有步骤的按钮都是type="submit",点击时都会触发表单的onSubmit事件,也就是handleSubmit函数——而这个函数里不管是不是最后一步,都执行了databases.createDocument,所以每次点Next都会提交一次数据,三次步骤就提交三次。
针对性修改方案
1. 拆分按钮类型与逻辑
把Next和Submit按钮分开处理:非最后一步的按钮用type="button",只做步骤切换;最后一步用type="submit"负责提交。修改按钮部分代码:
<div className="form-footer"> {step !== 0 && ( <button type="button" className="form-btn btn" onClick={() => handleNavigation("back")} > <FaArrowLeftLong /> </button> )} {/* 拆分Next和Submit按钮 */} {step === FormHeaders.length - 1 ? ( <button className="form-btn btn next" type="submit"> <h2 className="next-page"> Submit <i> <FaRegPaperPlane /> </i> </h2> </button> ) : ( <button className="form-btn btn next" type="button" onClick={() => handleNavigation("next")} > <h2 className="next-page"> Next Page <i> <FaArrowRightLong /> </i> </h2> </button> )} </div>
2. 修正提交函数逻辑
现在只有最后一步会触发handleSubmit,所以把提交和重置逻辑放在这里:
const handleSubmit = async (e) => { e.preventDefault(); try { // 仅在最后一步执行提交 const response = await databases.createDocument( DATABASE_ID, COLLECTION_ID_USERS, ID.unique(), formData ); console.log("Created", response); alert("Submission completed"); // 提交成功后重置表单和步骤 setFormData({ stdName: "", stdMiddleName: "", stdSurname: "", stdGender: "", stdPOB: "", stdDOB: "", fatherName: "", motherName: "", }); setStep(0); } catch (err) { console.error("提交失败", err); alert("提交失败,请重试"); } };
3. 简化导航函数
去掉handleNavigation里的submit分支,现在它只负责步骤切换:
const handleNavigation = (action) => { if (action === "next" && step < FormHeaders.length - 1) { setStep(step + 1); } else if (action === "back" && step > 0) { setStep(step - 1); } };
修改后的完整代码
import React, { useState } from "react"; import { COLLECTION_ID_USERS, DATABASE_ID, databases, } from "../../appwriteConfig"; import { ID } from "appwrite"; import { FaRegPaperPlane, FaArrowLeftLong, FaArrowRightLong, } from "react-icons/fa6"; import { FileUpload, ParentInfo, StudentInfo } from ".."; import * as yup from "yup"; import "./multistepForm.css"; const MultistepForm = () => { const [step, setStep] = useState(0); const [formData, setFormData] = useState({ stdName: "", stdMiddleName: "", stdSurname: "", stdGender: "", stdPOB: "", stdDOB: "", fatherName: "", motherName: "", }); const handleNavigation = (action) => { if (action === "next" && step < FormHeaders.length - 1) { setStep(step + 1); } else if (action === "back" && step > 0) { setStep(step - 1); } }; const handleSubmit = async (e) => { e.preventDefault(); try { const response = await databases.createDocument( DATABASE_ID, COLLECTION_ID_USERS, ID.unique(), formData ); console.log("Created", response); alert("Submission completed"); // 重置表单数据和步骤 setFormData({ stdName: "", stdMiddleName: "", stdSurname: "", stdGender: "", stdPOB: "", stdDOB: "", fatherName: "", motherName: "", }); setStep(0); } catch (err) { console.error("提交失败", err); alert("提交失败,请重试"); } }; const FormHeaders = [ "Student Information", "Parent Information", "Upload Files", ]; const StepDisplay = () => { switch (step) { case 0: return <StudentInfo formData={formData} setFormData={setFormData} />; case 1: return <ParentInfo formData={formData} setFormData={setFormData} />; default: return <FileUpload formData={formData} setFormData={setFormData} />; } }; return ( <div className="form"> <h2 className="form-title">Online Application</h2> <div className="progressbar"> <div style={{ width: step === 0 ? "33.3%" : step === 1 ? "66.6%" : "100%", }} ></div> </div> <div className="form-container"> <h1 className="form-header">{FormHeaders[step]}</h1> <div className="form-body"> <form onSubmit={handleSubmit} action="#"> {StepDisplay()} <div className="form-footer"> {step !== 0 && ( <button type="button" className="form-btn btn" onClick={() => handleNavigation("back")} > <FaArrowLeftLong /> </button> )} {step === FormHeaders.length - 1 ? ( <button className="form-btn btn next" type="submit"> <h2 className="next-page"> Submit <i> <FaRegPaperPlane /> </i> </h2> </button> ) : ( <button className="form-btn btn next" type="button" onClick={() => handleNavigation("next")} > <h2 className="next-page"> Next Page <i> <FaArrowRightLong /> </i> </h2> </button> )} </div> </form> </div> </div> </div> ); }; export default MultistepForm;
关键说明
- 非最后一步的按钮用
type="button",避免触发表单提交,只执行步骤切换。 - 仅在最后一步点击Submit时,才会调用Appwrite的创建文档接口,解决了多次提交的问题。
- 提交成功后,通过
setFormData重置表单数据,setStep(0)回到初始步骤,完成表单重置。
内容的提问来源于stack exchange,提问作者Jean Mako
相关产品推荐
相关产品推荐

