Formik 表单仅在单击第二个按钮后才有效? (使用 React Hooks、TypeScript、Formik、NextJS)
Formik form only validates after second button click? (Using React Hooks, TypeScript, Formik, NextJS)
我只是需要一双新鲜的眼睛来审视我的代码。所以问题是,我的代码确实有效并且确实验证了输入到表单中的代码数据。但是,它只在按下提交按钮两次后才执行此操作。经过试验,我一直没弄明白是什么问题。
它似乎确实首先尝试提交给我是 运行 的调用(这是对 Airtable 的 post 请求),在该调用处理请求之后,它会验证架构。
如果尚未填写所有字段,我最终会收到 422 处理错误。如果它们已满,则使用路由器推送下一页(提交)。
所以我想我想做的是在提交前验证表单域。有什么想法吗?
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;
为了清洁而缩短。
我确实像这样使用了 Formik,并且工作完美:
验证使用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>
我只是需要一双新鲜的眼睛来审视我的代码。所以问题是,我的代码确实有效并且确实验证了输入到表单中的代码数据。但是,它只在按下提交按钮两次后才执行此操作。经过试验,我一直没弄明白是什么问题。
它似乎确实首先尝试提交给我是 运行 的调用(这是对 Airtable 的 post 请求),在该调用处理请求之后,它会验证架构。
如果尚未填写所有字段,我最终会收到 422 处理错误。如果它们已满,则使用路由器推送下一页(提交)。
所以我想我想做的是在提交前验证表单域。有什么想法吗?
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;
为了清洁而缩短。
我确实像这样使用了 Formik,并且工作完美:
验证使用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>