Reputation: 25
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
Reputation: 592
I was able to modify your code and here are some of the adjustments I made.
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