skip to Main Content
import React, { useState } from "react";
import { FaAngleLeft, FaAngleRight, FaRegPaperPlane } from 
"react-icons/fa6";
import { FileUpload, ParentInfo, StudentInfo } from "..";
import "./multistepForm.css";

const MultistepForm = () => {
const [step, setStep] = useState(0);
const [formData, setFormData] = useState({
stdName: "",
stdMiddleName: "",
stdSurname: "",
stdGender: "",
stdPOB: "",
stdDOB: "",
fatherName: "",
motherName: "",
gradeLevel: "",
grade: "",
// Parent Info
prtName: "",
prtMiddleName: "",
prtSurname: "",
prtNational: "",
prtCountry: "",
prtState: "",
prtCity: "",
prtEmail: "",
prtPhone: "",
prtIDType: "",
prtIDNum: "",
// Files
prtIDImg: "",
stdTranscript: "",
stdImg: "",
});
function next() {
setStep((i) => {
  if (i >= FormHeaders.length - 1) return i;
  return i + 1;
});
}
function back() {
setStep((i) => {
  if (i <= 0) return i;
  return i - 1;
});
}
function onSubmit(e: FormEvent) {
e.preventDefault();
if (step !== FormHeaders.length - 1) return next();
alert("Submission completed");
}
const FormHeaders = [
"Student Information",
"Parent Information",
"Upload Files",
];

const StepDisplay = () => {
if (step === 0) {
  return <StudentInfo formData={formData} setFormData= 
{setFormData} />;
} else if (step === 1) {
  return <ParentInfo formData={formData} setFormData= 
{setFormData} />;
} else {
  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={onSubmit} action="#">
        {StepDisplay()}
        <div className="form-footer">
          {step !== 0 &&
            <button className="form-btn btn" onClick={back}>
              <FaAngleLeft />
            </button>
          }
          <button className="form-btn btn" type="submit">
            {step === FormHeaders.length - 1 ? (
              <i>
                <FaRegPaperPlane />
              </i>
            ) : (
              <i>
                <FaAngleRight />
              </i>
            )}
          </button>
        </div>
      </form>
    </div>
  </div>
</div>
);
};

export default MultistepForm;

I am building a multistep form with ReactJS and Vanilla JS and I ran into a problem with my Back button. The form has 3 pages and the back button works fine until I get to the last page, I cannot go back anymore (On page 2, I can still go back to page 1, but once I get to page 3, I cannot go back to page 2 as the back button stops working).
It does not display any error.
I have tried multiple ways to define the back function, but the problem is still the same.
It was working perfectly fine, until I added the onSubmit function (I am not very sure about it).

2

Answers


  1. maybe simplify a bit.
    a switch statement might be a good idea for step display

      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} />;
        }
      }
    

    combine all your step logic into one function

      const handleNavigation = (action) => {
        if (action === "next" && step < FormHeaders.length - 1) {
          setStep(step + 1);
        } else if (action === "back" && step > 0) {
          setStep(step - 1);
        } else if (action === "submit") {
          alert("Submission completed");
        }
      };
    

    so your submit would now look like

     const onSubmit = (e) => {
        e.preventDefault();
        if (step !== FormHeaders.length - 1) {
          handleNavigation("next");
        } else {
          handleNavigation("submit");
        }
      };
    

    finally add your new functions to your render

     return (
        <div className="form">
          <h2 className="form-title">Online Application</h2>
          <div className="progressbar">
            <div style={{ width: `${(step + 1) * 33.3}%` }}></div>
          </div>
          <div className="form-container">
            <h1 className="form-header">{FormHeaders[step]}</h1>
            <div className="form-body">
              <form onSubmit={onSubmit} action="#">
                {StepDisplay()}
                <div className="form-footer">
                  {step !== 0 && (
                    <button className="form-btn btn" onClick={() => handleNavigation("back")}>
                      <FaAngleLeft />
                    </button>
                  )}
                  <button className="form-btn btn" type="submit">
                    {step === FormHeaders.length - 1 ? <FaRegPaperPlane /> : <FaAngleRight />}
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      );
    };
    
    Login or Signup to reply.
  2. Your back button does not have a type attribute and when clicked, will implicitly submit the form, causing the onSubmit() function to fire. So on page 3, the step value is set to 1 in back() but then next() is called in onSubmit(), causing the value to go back to 2 straight away, making it seem like nothing happened.

    To fix this, you could consider setting type="button" on the back <button> so that it does not cause a form submission:

    const { useState } = React;
    
    var t=n(React),e={DefaultContext:{color:void 0,size:void 0,className:void 0,style:void 0,attr:void 0}}
    ;e.IconContext=React.createContext(e.DefaultContext);var r=["attr","size","title"];function n(t){
    return t&&t.__esModule?t:{default:t}}function o(t,e){if(null==t)return{};var r,n,o=c(t,e)
    ;if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(t);for(n=0;n<l.length;n++)r=l[n],
    e.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function c(t,e){
    if(null==t)return{};var r,n,o={},c=Object.keys(t);for(n=0;n<c.length;n++)r=c[n],e.indexOf(r)>=0||(o[r]=t[r]);return o}
    function l(){return l=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){
    var r=arguments[e];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(t[n]=r[n])}return t},
    l.apply(this,arguments)}function a(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){
    var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable
    }))),r.push.apply(r,n)}return r}function i(t){for(var e=1;e<arguments.length;e++){
    var r=null!=arguments[e]?arguments[e]:{};e%2?a(Object(r),!0).forEach((function(e){u(t,e,r[e])
    })):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(e){
    Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}function u(t,e,r){
    return(e=s(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}
    function s(t){var e=f(t,"string");return"symbol"==typeof e?e:String(e)}function f(t,e){
    if("object"!=typeof t||null===t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var n=r.call(t,e||"default")
    ;if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}
    return("string"===e?String:Number)(t)}function p(e){return e&&e.map(((e,r)=>t.default.createElement(e.tag,i({key:r
    },e.attr),p(e.child))))}function v(e){return r=>t.default.createElement(d,l({attr:i({},e.attr)},r),p(e.child))}
    function d(n){var c=e=>{var c,{attr:a,size:u,title:s}=n,f=o(n,r),p=u||e.size||"1em";return e.className&&(c=e.className),
    n.className&&(c=(c?c+" ":"")+n.className),t.default.createElement("svg",l({stroke:"currentColor",fill:"currentColor",
    strokeWidth:"0"},e.attr,a,f,{className:c,style:i(i({color:n.color||e.color},e.style),n.style),height:p,width:p,
    xmlns:"http://www.w3.org/2000/svg"}),s&&t.default.createElement("title",null,s),n.children)}
    ;return void 0!==e.IconContext?t.default.createElement(e.IconContext.Consumer,null,(t=>c(t))):c(e.DefaultContext)}
    function FaAngleLeft(t){return v({tag:"svg",attr:{viewBox:"0 0 320 512"},child:[{tag:"path",attr:{
    d:"M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"
    },child:[]}]})(t)}function FaAngleRight(t){return v({tag:"svg",attr:{viewBox:"0 0 320 512"},child:[{tag:"path",attr:{
    d:"M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"
    },child:[]}]})(t)}function FaRegPaperPlane(t){return v({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{
    d:"M16.1 260.2c-22.6 12.9-20.5 47.3 3.6 57.3L160 376V479.3c0 18.1 14.6 32.7 32.7 32.7c9.7 0 18.9-4.3 25.1-11.8l62-74.3 123.9 51.6c18.9 7.9 40.8-4.5 43.9-24.7l64-416c1.9-12.1-3.4-24.3-13.5-31.2s-23.3-7.5-34-1.4l-448 256zm52.1 25.5L409.7 90.6 190.1 336l1.2 1L68.2 285.7zM403.3 425.4L236.7 355.9 450.8 116.6 403.3 425.4z"
    },child:[]}]})(t)};
    
    const FileUpload = () => "FileUpload";
    const ParentInfo = () => "ParentInfo";
    const StudentInfo = () => "StudentInfo";
    
    const MultistepForm = () => {
      const [step, setStep] = useState(0);
      const [formData, setFormData] = useState({
        stdName: "",
        stdMiddleName: "",
        stdSurname: "",
        stdGender: "",
        stdPOB: "",
        stdDOB: "",
        fatherName: "",
        motherName: "",
        gradeLevel: "",
        grade: "",
        // Parent Info
        prtName: "",
        prtMiddleName: "",
        prtSurname: "",
        prtNational: "",
        prtCountry: "",
        prtState: "",
        prtCity: "",
        prtEmail: "",
        prtPhone: "",
        prtIDType: "",
        prtIDNum: "",
        // Files
        prtIDImg: "",
        stdTranscript: "",
        stdImg: "",
      });
      function next() {
        setStep((i) => {
          if (i >= FormHeaders.length - 1) return i;
          return i + 1;
        });
      }
      function back() {
        setStep((i) => {
          if (i <= 0) return i;
          return i - 1;
        });
      }
      function onSubmit(e) {
        e.preventDefault();
        if (step !== FormHeaders.length - 1) return next();
        alert("Submission completed");
      }
      const FormHeaders = [
        "Student Information",
        "Parent Information",
        "Upload Files",
      ];
    
      const StepDisplay = () => {
        if (step === 0) {
          return <StudentInfo formData={formData} setFormData={setFormData} />;
        } else if (step === 1) {
          return <ParentInfo formData={formData} setFormData={setFormData} />;
        } else {
          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={onSubmit} action="#">
                {StepDisplay()}
                <div className="form-footer">
                  {step !== 0 && (
                    <button className="form-btn btn" onClick={back} type="button">
                      <FaAngleLeft />
                    </button>
                  )}
                  <button className="form-btn btn" type="submit">
                    {step === FormHeaders.length - 1 ? (
                      <i>
                        <FaRegPaperPlane />
                      </i>
                    ) : (
                      <i>
                        <FaAngleRight />
                      </i>
                    )}
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      );
    };
    
    ReactDOM.createRoot(document.getElementById("app")).render(<MultistepForm />);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
    <div id="app"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search