Formik-Getting Started
文章目录

Formik-Getting Started

Formik: V2.1.4

React. Children.only expected to receive a single React element child

<Formik> 理论上接收一个 Child

里面一般是一个函数回调

而不是直接将一堆 component 扔到 <Formik> 里面

formik.values.xxx, Object is of type ‘unknown’

如果获取 formik 的时候没有设置 Generic Type 就会出现这样的错误

添加上 Type 即可

1
const formikBag = useFormikContext<CustomFormType>();

或者

1
2
3
4
5
<Formik>
(formikBag: FormikProps<CustomFormType>) => {

}
</Formik>

formik.values doesn’t changed when initialValue changed

重设 initialValue 的时候 formik.values 没有更新

经常是因为 Hooks 改变了 initialValues

1
2
3
4
5
6
7
<Formik
initialValues={initialValues}
onSubmit={submitForm}
enableReinitialize={true} // enableReinitialize default to FALSE, set it to TRUE
validateOnMount={false}
validationSchema={validationSchema}
>

Trigger Validation Only

表单的 validatio 可以单独 trigger

1
2
3
formik.validateForm()

formik.handleSubmit()

Field Level Validation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import React from 'react';
import {Formik, Form, Field} from 'formik';

/* Validate 方法, 返回 undefined 代表没有 Error */
function validateEmail(value) {
let error;
if (!value) {
error = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)) {
error = 'Invalid email address';
}
return error;
}

function validateUsername(value) {
let error;
if (value === 'admin') {
error = 'Nice try!';
}
return error;
}

export const FieldLevelValidationExample = () => (
<div>
<h1>Signup</h1>
<Formik
initialValues={{
username: '',
email: '',
}}
onSubmit={values => {
// same shape as initial values
console.log(values);
}}
>
{({errors, touched, validateField, validateForm}) => (
<Form>
{/** 单个 field, 设置 validate 方法并且通过 errors 获得到 error 内容 */}
<Field name="email" validate={validateEmail} />
{errors.email && touched.email && <div>{errors.email}</div>}

{/** 同上 */}
<Field name="username" validate={validateUsername} />
{errors.username && touched.username && <div>{errors.username}</div>}

{/** Trigger FIELD-LEVEL validation imperatively */}
<button type="button" onClick={() => validateField('username')}>
Check Username
</button>

{/** Trigger FORM-LEVEL validation imperatively */}
<button type="button" onClick={() => validateForm().then(() => console.log('blah')))}>
Validate All
</button>

<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
);

Different ways to get Formik

useFormik()

可以通过 formik hook 来进行各种设置和操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React from 'react';
import {useFormik} from 'formik';

const SignupForm = () => {
const formik = useFormik({
initialValues: {
firstName: '',
lastName: '',
email: '',
},
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
{......}
</form>
);
};

<Formik />

这个很麻烦, 如果要操作 form 那么就需要到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import React from 'react';
import {Formik} from 'formik';

const BasicExample = () => (
<div>
<h1>My Form</h1>
<Formik
initialValues={{name: 'jared'}}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
>
{props => {
// 从这里可以通过 useFormikContext() 来获取 formik
return (
<form onSubmit={props.handleSubmit}>
<input
type="text"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.name}
name="name"
/>
{props.errors.name && <div id="feedback">{props.errors.name}</div>}
<button type="submit">Submit</button>
</form>
)}
}
</Formik>
</div>
);

useFormikContext()

见上方代码, 只有在 Formik 元素里面 (通过 <Formik> 标签或者 withFormik() 包裹的内容里面) 才会有这一段上下文, 才能使用这个函数