很常見的功能。
懶人包
- 設定欄位的初始值
- 建立表單元件
- 把表單元件跟 formik 做資料雙向綁定
- 設定 submit 的 handler
Yup 的部分
其實就是建立一個 object,像這樣:
1 2 3 4 5
| const formSchema = Yup.object({ '欄位1': 規則1, '欄位2': 規則2, '欄位3': 規則3, })
|
規則的邏輯跟 propTypes 有點像,總之寫好後再跟 Formik 串起來就好了。
簡單來說會建立一個 Formik 的元件,只要把東西寫在 Formik
在這個元件裡,就可以利用它提供的 props 來做到下面這些事情:
- 設定欄位初始值
- 管理欄位的 state
- 用 Formik 的 action,例如 Reset 欄位的值
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
| import { View, TextInput, Text, Button } from "react-native"; import { globalStyles } from "../style/globalStyle"; import { Formik } from "formik";
interface Props { addReview: any }
const ReviewForm: React.FC<Props> = ({ addReview }) => { return ( <View style={globalStyles.container}> <Formik initialValues={{ title: '', body: '', rating: '', }} onSubmit={(values, action) => { // 這邊可以拿到欄位的值 addReview(values); // Formik 提供的 API action.resetForm(); }} > {/* 這邊是 render function,可以拿到 Formik 提供的 props, */} {(props) => ( <View> <TextInput style={globalStyles.input} placeholder="Review titile" onChangeText={props.handleChange('title')} value={props.values.title} /> <TextInput style={globalStyles.input} multiline placeholder="Review content" onChangeText={props.handleChange('body')} value={props.values.body} /> <TextInput style={globalStyles.input} keyboardType="numeric" placeholder="Rating (1, 5)" onChangeText={props.handleChange('rating')} value={props.values.rating} /> <Button title="Submit" onPress={props.handleSubmit} /> </View> )} </Formik> </View> ) } export default ReviewForm;
|
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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| import { View, TextInput, Text } from "react-native"; import { Button } from "../share/Button"; import { globalStyles } from "../style/globalStyle"; import { Formik } from "formik"; import * as Yup from "yup";
interface Props { addReview: any }
const reviewSchema = Yup.object({ title: Yup.string() .required() .min(4, 'Too short! It\'s must be greater than 4 charactor'), body: Yup.string() .required() .min(8, 'Too short! It\'s must be greater than 8 charactor'), rating: Yup.string() .required() .test('is num between 1 - 5', 'Rating must be a number 1 - 5', (val: any) => { return parseInt(val, 10) > 0 && parseInt(val, 10) < 6 }) })
const ReviewForm: React.FC<Props> = ({ addReview }) => { return ( <View style={globalStyles.container}> <Formik initialValues={{ title: '', body: '', rating: '', }} // 把規則傳入 props validationSchema={reviewSchema} onSubmit={(values, action) => { addReview(values); action.resetForm(); }} > {(props) => ( <View> <TextInput style={globalStyles.input} placeholder="Review titile" onChangeText={props.handleChange('title')} onBlur={props.handleBlur('title')} value={props.values.title} /> {/* Error Message */} <Text style={globalStyles.errorText}>{props.touched.title && props.errors.title}</Text> <TextInput style={globalStyles.input} multiline placeholder="Review content" onChangeText={props.handleChange('body')} onBlur={props.handleBlur('body')} value={props.values.body} /> <Text style={globalStyles.errorText}>{props.touched.body && props.errors.body}</Text> <TextInput style={globalStyles.input} keyboardType="numeric" placeholder="Rating (1, 5)" onChangeText={props.handleChange('rating')} onBlur={props.handleBlur('rating')} value={props.values.rating} /> <Text style={globalStyles.errorText}>{props.touched.rating && props.errors.rating}</Text> <Button title="Submit" onPress={props.handleSubmit} /> </View> )} </Formik> </View> ) } export default ReviewForm;
|
附註:props.touched.title
是為了做出「碰過以後」才顯示 error message,不然全部的欄位會一次 pop 出來。
最後附上一下完成效果: