こんにちは。iQeda [@iQeeeda] です。
最近 Next.js (React フレームワーク) を使っています。
と聞いていましたが、ライブラリを使うとめっちゃ簡単でした!
今回、フォームコンポネント作成ライブラリ Formik と、
Validation ライブラリの Yup を使ったサンプルコードを公開します。
Formik / Yum インストール
yarn コマンドで必要なライブラリをインストールします。
cd [プロジェクト]
# formik と yup インストール
yarn add formik yup
Formik
Formik はフォームコンポネント作成ライブラリです。
Yup
Yup は Formik 公式でも推奨されている Validation 実装ライブラリです。
- Formik と連携してバリデーションチェックしてくれます
- Formik の
validationSchema
に Yup オブジェクトスキーマをセットしますhandleSubmit
の際、エラーがあるとonSubmit
を呼び出さないようにしてくれます
- Yup は 非同期で動作します
公式ドキュメント
①お問い合わせフォーム → Slack 通知サンプル
- 氏名
- メールアドレス
- 電話番号
- お問い合わせ内容
上記項目の入力フォームです。送信すると Slack 通知するようにしています。
Slack にリクエストを投げるには yarn add axios
をしておいてください。
Slack とかどうでもいい方は handleSubmit
を空っぽにして好きな処理を記述してください。
import React, { Component } from 'react'; import axios from 'axios'; import Router from 'next/router'; import { Formik, Form, Field, ErrorMessage } from 'formik'; import * as Yup from 'yup'; const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/ const webhookURL = '[Slack の Webhook URL]'; /** * 非同期 Varidation */ const validationSchema = Yup.object().shape({ name: Yup.string() .required('氏名は必須です'), email: Yup.string() .email('メールアドレスの形式に誤りがあります') .required('メールアドレスは必須です'), tel: Yup.string() .matches(phoneRegExp, '電話番号の形式に誤りがあります'), content: Yup.string() .required('お問い合わせ内容は必須です'), }); class ContactForm extends Component { constructor(props) { super(props); this.defaultFormState = { name: '', email: '', tel: '', content: '', } } /** * フォーム送信後の処理 */ handleSubmit (form, { resetForm }) { let text = `■ 名前: ${form.name}\n■ メールアドレス: ${form.email}\n■ 電話番号: ${form.tel}\n■ お問い合わせ内容: ${form.content}` let data = { method: 'post', baseURL: webhookURL, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', }, data: `payload={ "text": "${ text }"}` }; try { axios.request(data) alert('送信しました') resetForm() Router.push('/contact') // リダイレクト } catch (error) { alert('送信に失敗しました') } } render() { return ( <Formik onSubmit={this.handleSubmit} initialValues={this.defaultFormState} validationSchema={validationSchema} > <Form> <div className="form-field"> <Field name="name" type="text" placeholder="氏名" /> </div> <div className="form-field"> <Field name="email" type="email" placeholder="メールアドレス" /> </div> <div className="form-field"> <Field name="tel" type="tel" placeholder="電話番号" /> </div> <div className="form-field"> <Field name="content" component="textarea" placeholder="お問い合わせ内容" /> </div> <div className="form-field"> <button type="submit"> 送信 </button> </div> <ErrorMessage name="name" component="div" className="invalidForm" /> <ErrorMessage name="email" component="div" className="invalidForm" /> <ErrorMessage name="tel" component="div" className="invalidForm" /> <ErrorMessage name="content" component="div" className="invalidForm" /> </Form> </Formik> ) } } export default ContactForm;
弊社のお問い合わせフォーム (https://eeeeg.tokyo/contact) はほとんど同じソースコードです。
②アカウント作成フォームサンプル
- 氏名
- メールアドレス
- パスワード
- パスワード再入力
上記項目の入力フォームです。
import React, { Component } from 'react'; import { Formik, Form, Field, ErrorMessage } from 'formik'; import * as Yup from 'yup'; /** * 非同期 Varidation */ const validationSchema = Yup.object().shape({ email: Yup.string() .email('メールアドレスの形式に誤りがあります') .required('メールアドレスは必須です'), password: Yup.string() .required('パスワード設定は必須です'), confirmPassword: Yup.string() .required('設定したパスワードを再入力してください') .oneOf([Yup.ref('password')], 'パスワードが一致しません') }); class RegistrationForm extends Component { constructor(props) { super(props); this.defaultFormState = { email: '', password: '', confirmPassword: '' } } /** * フォーム送信後の処理 */ handleSubmit (form) { // 値をコンソール表示 console.log(form) } render() { return ( <Formik onSubmit={this.handleSubmit} initialValues={this.defaultFormState} validationSchema={validationSchema} > <Form> <Field name="email" type="email" placeholder="Email" /> <Field name="password" type="password" placeholder="Password" /> <Field name="confirmPassword" type="password" placeholder="Confirm password" /> <button type="submit"> Submit </button> <ErrorMessage name="email" component="div" className="invalidForm" /> <ErrorMessage name="password" component="div" className="invalidForm" /> <ErrorMessage name="confirmPassword" component="div" className="invalidForm" /> </Form> </Formik> ) } } export default RegistrationForm;
(おまけ) handleSubmit 内で setState できない問題
フォーム送信したことを state 管理しようと思ったのですが、handleSubmit()
内で setState を実行することはできませんでした…
Formik は結果ステータスを props で渡すことができるみたいなので、
それで上手いことやる必要がありそうです。
参考) How to access form component state inside handleSubmit. · Issue #312 · jaredpalmer/formik · GitHub
関連記事
関連記事
お仕事ください!
僕が代表を務める 株式会社 EeeeG では Web 制作・システム開発・マーケティング相談を行っています。 なにかお困りごとがあれば、Twitter DM や Web サイトからお気軽にご相談ください。
カテゴリ「Develop」の最新記事