new coderrrr
new coderrrr

Reputation: 25

Unable to get the loading state while submitting the form using formik

I have a form component that includes an input field of type number and a button. I am using Formik to manage the form's state. The form component contains a modal that opens when I click the submit button.

The issue I am facing is that there is another button inside the modal, which is type submit. Clicking this button submits the form, but I am unable to access the isSubmitting state from Formik.

import React, { useState, useMemo } from "react";
import { Formik, Form, Field } from "formik";

const FormWithModal = () => {
  const [isModalOpen, setModalOpen] = useState(false);

  const Modal = useMemo(() => {
    if (!isModalOpen) return null;

    return (
      <div className="modal">
        <div className="modal-content">
          <h2>Modal</h2>
          <p>The form has been submitted!</p>
        </div>
      </div>
    );
  }, [isModalOpen]);

  return (
    <div>
      <h1>Form with Modal</h1>
      <Formik
        initialValues={{ numberInput: "" }}
        onSubmit={async (values, { setSubmitting }) => {
          setSubmitting(true);
          // Simulate API call or other async operation
          await new Promise((resolve) => setTimeout(resolve, 1000));
          setModalOpen(true);
          setSubmitting(false);
        }}
      >
        {({ isSubmitting }) => (
          <Form>
            <div>
              <label htmlFor="numberInput">Number:</label>
              <Field
                id="numberInput"
                name="numberInput"
                type="number"
                placeholder="Enter a number"
              />
            </div>
            <button type="submit" disabled={isSubmitting}>
              Submit
            </button>
            {Modal}
          </Form>
        )}
      </Formik>
    </div>
  );
};

export default FormWithModal;


Upvotes: 1

Views: 80

Answers (1)

Bankole Idris
Bankole Idris

Reputation: 592

I was able to modify your code and here are some of the adjustments I made.

  1. I added a yup validation to validate the numberinput
  2. I set the submit button in the formik form to a type "button", this way it doesn't trigger the form submission
  3. I passed the handleSubmit function in formik to the submit button inside the modal, so as to trigger the form submission
  4. Inside formik onSubmit function, I updated the formik loading states as well as the modal state in it and I wrapped it inside a setTimeout function.

I believe this should work for you on a basic level. Feel free to adjust the code to match your use case. see code below

import React, { useState } from "react";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";

const FormWithModal = () => {
  const [isModalOpen, setModalOpen] = useState(false);

  const validationSchema = Yup.object({
    numberInput: Yup.string().required("This field is required"),
  });

  return (
    <div>
      <h1>Form with Modal</h1>
      <Formik
        initialValues={{ numberInput: "" }}
        validationSchema={validationSchema}
        onSubmit={(values, { setSubmitting }) => {
          setTimeout(() => {
            console.log("Form submitted with values:", values);
            setSubmitting(false);
            setModalOpen(false);
          }, 2000);
        }}
      >
        {({ errors, touched, isSubmitting, isValid, handleSubmit }) => (
          <>
            <Form>
              <div>
                <label htmlFor="numberInput">Number:</label>
                <Field
                  id="numberInput"
                  name="numberInput"
                  type="text"
                  placeholder="Enter a number"
                />

                {errors.numberInput && touched.numberInput && (
                  <div className="error">{errors.numberInput}</div>
                )}
              </div>

              <button
                type="button"
                onClick={() => setModalOpen(true)}
                disabled={!isValid}
              >
                submit
              </button>
            </Form>

            {isModalOpen && (
              <div className="modal">
                <div className="modal-content">
                  <h2>Modal</h2>
                  <p>Click "Submit" to submit the form.</p>

                  <button type="button" onClick={() => setModalOpen(false)}>
                    Close Modal
                  </button>

                  <button
                    type="button"
                    onClick={handleSubmit as any}
                    disabled={isSubmitting}
                  >
                    {isSubmitting ? (
                      <span>
                        <span className="spinner"></span> Submitting...
                      </span>
                    ) : (
                      "Submit"
                    )}
                  </button>
                </div>
              </div>
            )}
          </>
        )}
      </Formik>
    </div>
  );
};

export default FormWithModal;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>

Upvotes: 4

Related Questions