formikとyupでReactのFormを作成
概要
formik を使って、React の form を作成方法についてまとめます。
formik は React で Form を作成するときに便利なライブラリです。
初期値やバリデーションを React らしく作成可能です。
また Yup というバリデーションを簡潔に記述できるライブラリをサポートしており、組み合わせることで直感的な Form 作成を実現できます。
formik はチュートリアル(リンク)がとてもわかりやすいので、そちらをお勧めします。
本記事もチュートリアルの内容を参考にしてソースコードを記述します。
本記事のサンプルコードは以下です。
実装
formik にはuseFormik
とFormik
を用いた記述方法があります。
useFormik
は Hooks を使用した実装方法で、Formik
は API コンポーネントを使用した実装方法です。
useFormik Yup なし
useFormik
を用いたときのサンプルコードです。
引数にinitialValues
(初期値)、validate
(バリデーション)、onSubmit
(クリック時の挙動)を渡します。
validate
は Yup を使わないと関数(最大値、最小値、有効な文字、エラーメッセージなど)を自作することになります。
import { FC } from "react";
import { useFormik } from "formik";
type valuesType = {
firstName: string;
lastName: string;
email: string;
};
type errorsType = {
firstName?: string;
lastName?: string;
email?: string;
};
const validate = (values: valuesType) => {
const errors: errorsType = {};
if (!values.firstName) {
errors.firstName = "Required";
} else if (values.firstName.length > 15) {
errors.firstName = "Must be 15 characters or less";
}
if (!values.lastName) {
errors.lastName = "Required";
} else if (values.lastName.length > 20) {
errors.lastName = "Must be 20 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 SignupForm: FC = () => {
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
email: "",
},
validate,
onSubmit: (values) => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<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}
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.lastName}
/>
{formik.touched.lastName && formik.errors.lastName ? (
<div>{formik.errors.lastName}</div>
) : null}
</div>
<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>
);
};
export default SignupForm;
useFormik Yup あり
useFormik
と Yup
を組み合わせたときのサンプルコードです。
引数のvalidation
がvalidationSchema
に変更され、Yup
オブジェクトを直接渡すことが可能です。
バリデーションを自作するよりも簡潔に記述できるようになりました。
import { FC } from "react";
import { useFormik } from "formik";
import * as Yup from "yup";
const SignupForm: FC = () => {
const formik = useFormik({
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) => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<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}
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.lastName}
/>
{formik.touched.lastName && formik.errors.lastName ? (
<div>{formik.errors.lastName}</div>
) : null}
<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}
<button type="submit">Submit</button>
</form>
);
};
export default SignupForm;
Formik Yup あり
Formik
を用いたサンプルコードです。
Field
、Form
、ErrorMessage
といった関数も formik に用意されており、これらを組み合わせることでuseFormik
を使うよりもさらに簡潔に書くことが可能です。
import { FC } from "react";
import { Formik, Field, Form, ErrorMessage } from "formik";
import * as Yup from "yup";
const SignupForm: FC = () => {
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);
}}
>
<Form>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" type="text" />
<ErrorMessage name="firstName" />
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" type="text" />
<ErrorMessage name="lastName" />
</div>
<div>
<label htmlFor="email">Email Address</label>
<Field name="email" type="email" />
<ErrorMessage name="email" />
</div>
<button type="submit">Submit</button>
</Form>
</Formik>
);
};
export default SignupForm;
動作確認
実行
git clone https://github.com/Msksgm/react-formik-example.git
cd react-formik-example
yarn
yarn start
画面
localhost:3000
に以下のような画面が表示されます。
すべての Form が同じ動作をしますが、<Formik />
を使用することでソースコードの記述量が激減します。
ですので、保守性の観点も含めて、formik を使うときには<Formik />
を使うようにしています。
checkbox を使うときの書き方もチュートリアルに記述してあるので参考にしてみてください。
localhost3000
参考
Discussion