![](/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.