Open10
formik を使う前に、知っておきたかった点をまとめてみた
公式チュートリアルを参考に知っておきたかった点をまとめる
サンプル
ミニマムのサンプル。
import React from 'react';
import { useFormik } from 'formik';
const SignupForm = () => {
// Pass the useFormik() hook initial form values and a submit function that will
// be called when the form is submitted
const formik = useFormik({
initialValues: {
email: '',
},
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
/>
<button type="submit">Submit</button>
</form>
);
};
初期化
useFormik
に初期値や送信用の関数、バリデーションの関数を渡す。
useFormik({
initialValues: { name: "" } // 初期値
onSubmit: () => {}, // 送信用の関数
validate: (values) => {} // バリデーション用の関数
})
インプット要素に指定するメソッド
-
formik.handleChange
- フォームの値を更新するための関数。(フォームを自作した人は分かると思うが、送信ボタンをクリックする前に、フォームの値を更新するための state 管理をやってくれる)
-
formik.handleBlur
- 指定しておくとフォームが入力されたフラグ(
formik.touched
) を使えるようになる。エラーメッセージを出す時に{(formik.touched.firstName && formik.errors.firstName) && ( <div>{formik.errors.firstName}</div>}
と指定しておくと入力されたフォームのみエラーメッセージを出せる。
- 指定しておくとフォームが入力されたフラグ(
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.firstName}
/>
{formik.touched.firstName && formik.errors.firstName ? (
<div>{formik.errors.firstName}</div>
) : null}
バリデーションライブラリ Yup
ライブラリ Yup
を使うと、useFormik
に validationSchema
を渡して、以下のようにバリデーションを書くことができる
const formik = useFormik({
validationSchema: Yup.object({
name: Yup.string()
.max(15, 'Must be 15 characters or less')
.required('Required'),
email: Yup.string().email('Invalid email address').required('Required'),
}),
});
getFieldProps で簡潔に書く
formik.getFieldProps('インプット要素のID')
を指定すると、onChange
, onBlur
, value
, name
を指定する必要がなくなる。
<input
id="firstName"
type="text"
{...formik.getFieldProps('firstName')}
/>
コンポーネント形式で書く
useFormik
を、<Formik/>
コンポーネントに置き換えても書ける
import React from 'react';
import { Formik } from 'formik';
import * as Yup from 'yup';
const SignupForm = () => {
return (
<Formik
initialValues={{ firstName: '', lastName: '', email: '' }}
validationSchema={Yup.object({
firstName: Yup.string()
.max(15, 'Must be 15 characters or less')
.required('Required'),
lastName: Yup.string()
.max(20, 'Must be 20 characters or less')
.required('Required'),
email: Yup.string().email('Invalid email address').required('Required'),
})}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{formik => (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
type="text"
{...formik.getFieldProps('firstName')}
/>
{formik.touched.firstName && formik.errors.firstName ? (
<div>{formik.errors.firstName}</div>
) : null}
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
type="text"
{...formik.getFieldProps('lastName')}
/>
{formik.touched.lastName && formik.errors.lastName ? (
<div>{formik.errors.lastName}</div>
) : null}
<label htmlFor="email">Email Address</label>
<input id="email" type="email" {...formik.getFieldProps('email')} />
{formik.touched.email && formik.errors.email ? (
<div>{formik.errors.email}</div>
) : null}
<button type="submit">Submit</button>
</form>
)}
</Formik>
);
};
Material UI Kit + Formik + Yup を使う
Yup の日本語化は以下のように実装する
Yup.string().max(2, '2文字以内で入力してください').required('必須項目です')
MUI と formik を合わせて使うには以下のように実装する
<TextField
id='title'
type={'text'}
label="タイトル"
{...formik.getFieldProps('title')}
error={Boolean(formik.touched.title && formik.errors.title)}
helperText={formik.touched.title && formik.errors.title ? formik.errors.title : null}
/>
フルサンプル
const formik = useFormik({
initialValues: {
title: '',
submit: null
},
validationSchema: Yup.object({
title: Yup.string().max(2, '2文字以内で入力してください').required('必須項目です'),
}),
onSubmit: async (values, helpers) => {
console.log(values)
}
});
return (
<>
<form
onSubmit={formik.handleSubmit}>
<TextField
id='title'
type={'text'}
label="タイトル"
{...formik.getFieldProps('title')}
error={Boolean(formik.touched.title && formik.errors.title)}
helperText={formik.touched.title && formik.errors.title ? formik.errors.title : null}
/>
<Button type='submit'>
保存
</Button>
</form>
</>
);
formik を MUI のセレクトコンポーネントに組み込む
<FormControl fullWidth>
<InputLabel id="result-category">カテゴリ</InputLabel>
<Select
labelId="result-category"
id='category'
label="カテゴリ"
{...formik.getFieldProps('category')}
error={Boolean(formik.touched.category && formik.errors.category)}
>
{categoryLabelList.map((categoryLabel) => {
return (
<MenuItem
key={categoryLabel.id}
value={categoryLabel.id}
>
{categoryLabel.name}
</MenuItem>
)
})}
</Select>
<FormHelperText>{formik.touched.category && formik.errors.category ? formik.errors.category : null}</FormHelperText>
</FormControl>
Fileをアップロードする
<>
<Button
variant="contained"
onClick={handleUploadClick}
>
画像をアップロード
</Button>
<input
ref={inputFileRef}
accept="image/*"
style={{ display: 'none' }}
id="avatar"
name="avatar"
type="file"
onChange={(event) => {
formik.setFieldValue(
"avatar",
event.target.files !== null
? event.target.files[0]
: null
);
}}
/>
</>