Formik是一个小型库。由React组件和hooks组成,它内置了表单的state管理操作,同时使用了Context,能够让表单组件多层嵌套,不再需要一层层传递。它也可以便捷实现自定义校验。
它的底层是ant design的组件。
安装:npm install formik --save
或 yarn add formik
onSubmit: (values: Values, formikBag: FormikBag) => void | Promise<any>
该方法和 ant design
中 form 的 onChange 使用方法类似。
不同组件获取值的方法:
Input 组件:onChange=(e)=>{ console.log(e.target.value) };
Select 组件: onChange=(e)=>{ console.log(e) };
手动强制设置一个表单的值,格式:
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void
如:
setFieldValue('name','zhanhsan');
validate?: (values: Values) => FormikErrors<Values> | Promise<any>
如:
const validate = values => {
const errors = {};
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address';
}
return errors;
};
主要属性:initialValues
(必须,否则会出现错误),validate
,onSubmit
,onChange
等。
案例是一个邮箱、密码框的情景。
我们可以从中看出自定义校验如何规定、errors 如何设置错误提示信息。
import React from 'react';
import { Formik } from 'formik';
const Basic = () => (
<div>
<h1>Anywhere in your app!</h1>
<Formik
initialValues={{ email: '', password: '' }}
validate={values => {
const errors = {};
if (!values.email) {
errors.email = 'Required';
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
) {
errors.email = 'Invalid email address';
}
return errors;
}}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
/* and other goodies */
}) => (
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
/>
{errors.email && touched.email && errors.email}
<input
type="password"
name="password"
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{errors.password && touched.password && errors.password}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</form>
)}
</Formik>
</div>
);
export default Basic;
However, to save you time, Formik comes with a few extra components to make life easier and less verbose: <Form />, <Field />, and <ErrorMessage />
. They use React context to hook into the parent <Formik />
state/methods.
按照官方说法,上述案例可以更加缩减,直接使用标签,使用React的上下文传递父组件的 state 或者方法:
import React from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
const Basic = () => (
<div>
<h1>Any place in your app!</h1>
<Formik
initialValues={{ email: '', password: '' }}
validate={values => {
const errors = {};
if (!values.email) {
errors.email = 'Required';
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
) {
errors.email = 'Invalid email address';
}
return errors;
}}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({ isSubmitting }) => (
<Form>
<Field type="email" name="email" />
<ErrorMessage name="email" component="div" />
<Field type="password" name="password" />
<ErrorMessage name="password" component="div" />
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</Form>
)}
</Formik>
</div>
);
export default Basic;
initialValues
(必须,否则会出现错误),validate
,onSubmit
这些属性的值可以提取为变量,在外面写,如下:
const initialValues = {
firstName: '',
lastName: '',
email: '',
};
const validate = values => {
const errors = {};
if (!values.firstName) {
errors.firstName = 'Required';
} else if (values.firstName.length > 15) {
errors.firstName = 'Must be 15 characters or less';
}
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address';
}
return errors;
};
const onSubmit = values => {
alert(JSON.stringify(values, null, 2));
};
const SignupForm = () => {
const formik = useFormik({
initialValues,
validate,
onSubmit,
});
return (
<form onSubmit={formik.handleSubmit}>
{...}
</form>
)}
开发中遇到的问题:
原因: 未写 initialValues,Formik将值存储在initialValues中。
见我的这篇博客:在Modal中使用了Formik,如何提交?