[note] Formik 筆記
- Formik @ Official Website
- Formik Examples @ Github
- Formik Debug Component @ Github
關於那些小細節 Tips
- Formik 會使用
<input>
欄位中的name
屬性來決定該value
要保存在哪個內部的 key 中。 - Formik 中包括
values
,errors
,touched
物件,裡面的key
都會和<input>
的name
對應。 - Formik 在使用 radio button 時,當帶入的 value 是「數值」需特別留意,因為存在
field
的值會是「數值」,但存入 Formik 的meta
中會變成「字串」,這會導致 Formik 沒辦法匹配正確,進而使得該 input 沒辦法被勾選(checked),但在 Formik 中又會設值的情況(參考這個 Gist)。
useFormik
基本使用
使用 Formik 中的 values
物件:
import { useFormik } from 'formik';
const SignupForm = () => {
// STEP 1: useFormik
const formik = useFormik({
// STEP 2-1:建立初始值
initialValues: { email: '' },
// STEP 2-2:在 onSubmit 時透過 `values` 物件取得表單中的內容
onSubmit: values => {
console.log(JSON.stringify(values, null, 2));
},
});
return (
// STEP 3: 在 onSubmit 事件中帶入 `formik.handleSubmit`
<form onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="email">Email Address</label>
{/* STEP 4-1:建立 input 欄位,formik 會用 input 的 name 來作為內部的 key */}
<input id="email" name="email" type="email"
{/* STEP 4-2: invoke `formik.handleChange` when input onchange */}
onChange={formik.handleChange}
{/* STEP 4-3: 使用 values 物件取回該欄位的值 */}
value={formik.values.email}
/>
</div>
<button type="submit">Submit</button>
</form>
);
};
表單驗證:手動處理(validate)
使用 Formik 中的 errors
物件,並搭配 validate
屬性:
// STEP 1:建立 validate
const validate = (values) => {
const errors = {};
if (!values.firstName) {
errors.firstName = 'Required first name';
} else if (values.firstName.length > 15) {
errors.firstName = 'Must be 15 characters or less';
}
return errors;
};
const SignupForm = () => {
const formik = useFormik({
initialValues: { email: '' },
// STEP 2:放入 validate 函式
validate,
onSubmit: (values) => {
console.log(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
/>
{/* STEP 3: 有錯誤時顯示錯誤 */}
{formik.errors.email ? <div>{formik.errors.email}</div> : null}
</div>
<button type="submit">Submit</button>
</form>
);
};
- 預設的情況下,在每一次 onChange 及 onSubmit 時,Formik 都會促發 validate 函式(如果有給的話),只有在
errors
為空物件時,才會真的把表單送出。
表單驗證:搭配 Yup(validationSchema)
在 Formik 中除了 validate
可以手動驗證表的欄外之外,額外提供 validationSchema
可以搭配 Yup 來做欄位的資料驗證:
import React from 'react';
import { useFormik } from 'formik';
// STEP 1:匯入 Yup
import * as Yup from 'yup';
const SignupForm = () => {
const formik = useFormik({
initialValues: { email: '' },
// STEP 2:搭配 Yup 使用 validationSchema
validationSchema: Yup.object({
firstName: Yup.string().max(15, '至少要超過 15 個字').required('firstName 為必填'),
email: Yup.string().email('無效的 Email').required('email 為必填'),
}),
onSubmit: (values) => {
console.log(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.email}
/>
{formik.touched.email && formik.errors.email ? <div>{formik.errors.email}</div> : null}
</div>
<button type="submit">Submit</button>
</form>
);
};
檢驗表單是否碰過
使用 Formik 中的 touched
物件,搭配在 input
欄位上的 onBlur
事件:
const SignupForm = () => {
const formik = useFormik({
/* ... */
});
return (
<form onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
// STEP 1: 使用 onBlur 搭配 formik.handleBlur
onBlur={formik.handleBlur}
/>
{/* STEP 2: 取得 touched 物件的值 */}
{formik.touched.firstName && formik.errors.firstName ? (
<div>{formik.errors.firstName}</div>
) : null}
</div>
<button type="submit">Submit</button>
</form>
);
};