Reputation: 25
I just need a fresh pair of eyes to look at my code. So the problem is, my code does work and does validate the code data input into a form. However, it only does this after pressing the submit button twice. After experimenting, I have not been able to figure out what the problem is.
It seems that it does attempt to submit to the call I'm running first (it is a post request to Airtable), and after that call processes the request, it then validates the schema.
I end up getting a 422 Processing Error if all the fields are not filled yet. If they are filled, the next page (Submit) is pushed with the Router.
So I guess what I want to do is validate the form fields before submission. Any ideas?
interface FormValues {
firstName: string,
email: string,
}
const SchedulePage: NextPage = () => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const postSubmit = (firstName: string, email: string) => {
setLoading(true);
airtableApi
.postAirtableSchedules(firstName, email)
.then(() => {
setLoading(false);
Router.push('/submitted');
})
.catch((err) => {
setLoading(false);
setError(err.message);
});
};
const formik = useFormik({
initialValues: {
firstName: '',
email: '',
}, validate() {
const errors: FormikErrors<FormValues> = {}
// Add the touched to avoid the validator validating all fields at once
if (formik.touched.email && !formik.values.email) {
errors.email = "Email is required";
}
if (formik.touched.firstName && !formik.values.firstName) {
errors.firstName = "First name is required";
}
return errors;
},
onSubmit: (values: any) => {
postSubmit(values.firstName, values.email);
},
});
console.log(formik.errors.email);
return (
<>
<div className="absolute w-full pt-20 bg-gray-150">
<div className="container flex items-center justify-center h-full mx-auto">
<div className="relative flex-col items-center justify-center w-full h-full md:h-auto md:w-3/4 lg:w-2/5">
<div className="flex flex-col items-center w-full h-full bg-white rounded-sm shadow-sm flex-start">
<div className="flex flex-col w-full border-t border-gray-200 bg-gray-150">
<div className="flex items-center justify-center w-full py-6 bg-black">
<img src={'https://ridebeyond.com/wp-content/uploads/2020/08/logo_beyond_white.png'} />
</div>
<div className="flex items-center justify-center w-full">
<Text
label="Please sign up for a meeting."
marginTop={6}
marginBottom={2}
/>
</div>
</div>
<div className="flex flex-col items-center justify-center w-4/5 mb-10 lg:w-2/3">
<TextInput
type={TextInputType.TEXT}
id="firstName"
name="firstName"
onChange={(event) => {
formik.handleChange(event);
}}
value={formik.values.firstName}
floatText="First Name"
marginTop={1}
error={formik.errors.firstName}
/>
<TextInput
type={TextInputType.EMAIL}
id="email"
name="email"
onChange={(event) => {
formik.handleChange(event);
}}
value={formik.values.email}
floatText="Email"
marginTop={10}
error={formik.errors.email}
/>
{error && <Text label={error} marginTop={16} />}
<Button
text="Submit"
marginTop={10}
marginBottom={16}
size={ButtonSize.LG}
handleClick={formik.handleSubmit}
isLoading={loading}
/>
</div>
</div>
</div>
</div>
</div>
</>
);
};
export default SchedulePage;
Shortened for cleanliness.
Upvotes: 1
Views: 1564
Reputation: 4588
I did use Formik like this and works perfect:
For validation use Yup
<Formik
initialValues={
firstName: '',
email: ''
}
validationSchema={
Yup.object().shape({
email: Yup.string()
.email("Must be a valid email")
.max(255)
.required("Email is required"),
firstname: Yup.string()
.max(255)
.required("First name is required"),
})
}
onSubmit={(e:{firstName: string,email: string}, { resetForm }) => {
let val: any = e;
postSubmit (e.firstName,e.email);
// ur rest logic
// resetForm({
// values: {
// ...e,
// },
});
}}
>
{({ handleChange, values, initialValues, errors }) => (
// Your form jsx
)}
</Formik>
Upvotes: 1