
こんにちは。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」の最新記事

TerraformによるLinodeインスタンス新規作成サンプル
【Fingerprint】CircleCIがSSHできない問題解決
【Laravel】セッションタイムアウト後のログイン処理で前回URLに遷移するバグ修正
M1 Mac(2021)でanyenv/phpenvの初期設定!