简体   繁体   English

Formik 表单仅在第二个按钮单击后验证? (使用 React Hooks,TypeScript,Formik,NextJS)

[英]Formik form only validates after second button click? (Using React Hooks, TypeScript, Formik, NextJS)

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.似乎它确实尝试提交给我首先运行的调用(它是对 Airtable 的发布请求),并且在该调用处理请求之后,它然后验证架构。

I end up getting a 422 Processing Error if all the fields are not filled yet.如果尚未填写所有字段,我最终会收到 422 处理错误。 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.为了清洁而缩短。

I did use Formik like this and works perfect:我确实像这样使用过 Formik 并且效果很好:

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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM