![](/img/trans.png)
[英]React formik form validation: How to initially have submit button disabled
[英]How to clear status before validation on Formik submit?
我正在使用带有 yup 验证的 Formik,遵循以下模式:
const handleSubmit = async (values, { setStatus }) => {
setStatus(''); // clean errors messages
try {
... do submit work ...
const res = await sendData( convertValues(values)); //
... more work
} catch (e) {
console.error(e);
setStatus('an error occurred '...);
}
};
const validationSchema = Yup.object({
code: Yup.string().required(t('Required')),
....
});
return (
<Formik onSubmit={handleSubmit} initialValues={initialValues} validationSchema={validationSchema}>
{({ setFieldValue, status }) => (
<Form>
....
<MyErrorComponent msg={status} />
</Form>
)}
</Formik>
);
这在这种情况下有问题:
handleSubmit
内部发生了一些错误。 状态中显示错误消息 发生这种情况是因为验证发生在提交之前,因此不调用setStatus('')
。 处理此问题的推荐方法是什么?
我认为你应该使用这样的东西:
<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, { resetForm }) => {
let val = e;
postSubmit (e.firstName,e.email);
// ur rest logic
// resetForm({
// values: {
// ...e,
// },
});
}}
>
{({ handleChange, values, initialValues, errors }) => (
// Your form jsx
)}
</Formik>
不要将useState
与 formik 一起使用,让 Formik 处理错误和验证!
我确实使用了这种模式,并且效果很好。
如果您没有找到方法,请分享您的表格,以便为您制作!
它对 onMouseDown 事件有一个验证过程。 您可以通过防止提交按钮上的默认设置来避免重复验证。
onMouseDown={(event: any): void => {
event.preventDefault();
}}
之后Formik自动清除状态
你可以为 formik 使用钩子useFormik
import { useFormik } from 'formik';
....
const formik = useFormik({
initialValues: {},
validationSchema={validationSchema}
onSubmit: values => {
handleSubmit(values);
},
});
const handleSubmit = async (values, { setStatus }) => {
try {
... do submit work ...
const res = await sendData( convertValues(values)); //
... more work
} catch (e) {
console.error(e);
//change statuvalues or display errors
//formik.setValue...
//formik.setError...
}
};
return (
<form onSubmit={formik.handleSubmit}>
....
<button type="submit">Submit</button>
</form>
);
您可以通过更改的值来控制 Formik 何时运行验证
<Formik validateOnChange> and / or
<Formik validateOnBlur> props depending on your needs.
默认情况下,Formik 将运行如下验证方法:
将道具传递给您的 Formik
validateOnChange={false} and
validateOnBlur={false}
为了更好地理解检查文档Formik Validation
我个人认为状态只是为了通知用户。 所以我会通过告诉他们有错误从小吃店/通知中通知他们。 然后,如果验证表单上有错误,我会删除它们,以便他们专注于修复错误的表单
这是一个示例代码和沙箱:
const validationSchema = yup.object().shape({
name: yup.string().required("Required")
});
const initialValues = {
name: "John Doe"
};
export const FormikTextField = ({ className, ...props }) => {
const [field, meta] = useField(props);
const { setStatus } = useFormikContext();
useEffect(() => {
if (meta.error) {
setStatus("");
}
}, [meta.error]);
return (
<>
<TextField
variant="outlined"
{...field}
{...props}
FormHelperTextProps={{ error: true }}
helperText={meta.error && meta.touched ? String(meta.error) : null}
aria-invalid={Boolean(meta.error)}
/>
</>
);
};
export default function App() {
const handleSubmit = (values, { setStatus }) => {
setStatus("status set!");
};
return (
<Formik
enableReinitialize
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => (
<Form>
{props.status && <p>{props.status}</p>}
<div className="App">
<FormikTextField name="name" variant="outlined" label="Name" />
<Button type="submit" variant="contained">
Submit
</Button>
</div>
</Form>
)}
</Formik>
);
}
是的,你的假设是正确的。 提交前完成表单验证。 您需要做的是,在自定义验证 function 中添加此错误清除步骤
const validate = values =>
{
// If you want some other custom validations, you can do that on values parameter
setStatus('');
};
const handleSubmit = async (values, { setStatus }) => {
// setStatus(''); // clean errors messages
try {
... do submit work ...
const res = await sendData( convertValues(values)); //
... more work
} catch (e) {
console.error(e);
setStatus('an error occurred '...);
}
};
const validationSchema = Yup.object({
code: Yup.string().required(t('Required')),
....
});
return (
<Formik onSubmit={handleSubmit} initialValues={initialValues} validationSchema={validationSchema}
validate={validate}>
{({ setFieldValue, status }) => (
<Form>
....
<MyErrorComponent msg={status} />
</Form>
)}
</Formik>
);
有关更多详细信息,请查看此CombinedValidations示例。
当您使用异步表单提交时,如async-submission所示。 您可能必须通过创建这样的包装器 Promise 来使用异步验证 function 或使您的表单提交同步。
以上示例的链接来自官方文档。
您可以在每个表单输入中添加validate
调用,以便用户更改输入status
消息时将被清除。
import React from "react";
import ReactDOM from "react-dom";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
const schema = Yup.object().shape({
name: Yup.string().required("Name"),
age: Yup.number().required("Number").positive().integer()
});
const MyForm = () => (
<div>
<Formik
initialValues={{ name: "", age: "" }}
validationSchema={schema}
onSubmit={(values, actions) => {
console.log("submited", values);
actions.setStatus("")
try {
throw new Error("Something went wrong")
}
catch (error) {
actions.setStatus(error.message);
}
}}
render={({
status,
isSubmitting,
setStatus,
dirty,
values,
handleReset,
errors,
touched
}) => {
const field_props_with_validation = function() {
const name = arguments[0];
const type = arguments[1] || "text";
const placeholder = arguments[2] || "";
return {
name,
type,
placeholder,
validate: () => {
setStatus("");
}
}
}
return (
<Form>
{status}
{["name", "age"].map((field, key) => (
<div key={key}>
<Field {...field_props_with_validation(field)} />
<ErrorMessage name={field} component="div" />
</div>
))}
<button type="submit">Enter</button>
</Form>
);
}}
/>
</div>
);
function App() {
return (
<div className="App">
<h1>Registration Form</h1>
<MyForm />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
可以使用validateOnChange
道具在表单输入更改时disabled
validation
,并且仅在用户提交表单时进行validate
。
注意:在这种情况下,您必须处理验证,在用户重新提交表单之前,状态不会被清除。
import React from "react";
import ReactDOM from "react-dom";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
const schema = Yup.object().shape({
name: Yup.string().required("Name"),
age: Yup.number().required("Number").positive().integer()
});
const MyForm = () => (
<div>
<Formik
initialValues={{ name: "", age: "" }}
validateOnChange={false}
onSubmit={async (values, actions) => {
actions.setStatus("");
await schema.validate(values, {
abortEarly: false // not to stop on single validation fail
// and return single error message
})
.then(() => {
try {
throw new Error("Some error")
}
catch (error) {
actions.setStatus(error.message);
}
})
.catch(err => {
let errors = {};
Object.keys(values).forEach((key, idx) => {
if (err && err.errors && err.errors[idx]) {
errors[key] = err.errors[idx];
}
});
actions.setErrors(errors)
})
}}
render={({
status,
isSubmitting,
dirty,
values,
handleReset,
errors,
touched
}) => {
return (
<Form>
{status}
{["name", "age"].map((field, key) => (
<div key={key}>
<Field name={field} type="text" placeholder={field} />
<ErrorMessage name={field} component="div" />
</div>
))}
<button type="submit">Enter</button>
</Form>
);
}}
/>
</div>
);
function App() {
return (
<div className="App">
<h1>Registration Form</h1>
<MyForm />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.