JavaScript
reactjs
Formik
Yup

FormikでReactに簡単にフォームを導入!! ~0からreact習得記 day 17~

これまでのreact習得記は、こちらから閲覧できます。

1_M1ae_X1VwJm74dGWpgt85A.png (19.3 kB)

はじめに

株式会社VRizeでインターンとして勤務しているryo_tです。
短期目標に「1ヶ月でReactのUIを開発できるように」と伝えられたので、Reactはほとんど未経験ですが一歩一歩頑張って行きます。

目的

  • Formikを知る / 実際に触ってみる

概要

Formikとは

Formikとは、Reactでフォームを扱う際の面倒な問題を解決してくれます。

  • フォームのStateをPropsに変換
  • Validationとかエラーのメッセージが簡単に表示出来る
  • フォームの送信時のデータ制御

Formikでvalidationを使用する為に、Yupと言うライブラリも使用します。

導入

準備

create-react-app

create-react-appを使用して、実装準備を行います。
ターミナルから下記のコマンドを実行します。

#プロジェクト作成
create-react-app プロジェクト名

#プロジェクトディレクトリへ移動
cd プロジェクト名

#yarnインストール
yarn install

#FormikとYupをインストール
yarn add formik yup

#yarnを実行
yarn start

実装

HighOrderComponentsを使用して実装

HighOrderComponentsを使用して、メールアドレスを送信するフォームを作成します。

Form.js
import React from "react";
import { render } from "react-dom";
import { withFormik } from "formik";
import Yup from "yup";

// Formikで覆う関数
// Destructuringで各値にpropsを代入
const MyInnerForm = props => {
  const {
    values,
    touched,
    errors,
    dirty,
    isSubmitting,
    handleChange,
    handleBlur,
    handleSubmit,
    handleReset
  } = props;
// 表示するコンポーネントを定義
  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="email" style={{ display: "block" }}>
        Email
      </label>
      <input
        id="email"
        placeholder="Enter your email"
        type="text"
        value={values.email}
        onChange={handleChange}
        onBlur={handleBlur}
        className={
          errors.email && touched.email ? "text-input error" : "text-input"
        }
      />
      {errors.email &&
      touched.email && <div className="input-feedback">{errors.email}</div>}

      <button
        type="button"
        className="outline"
        onClick={handleReset}
        disabled={!dirty || isSubmitting}
      >
        Reset
      </button>
      <button type="submit" disabled={isSubmitting}>
        Submit
      </button>

    </form>
  );
};

const EnhancedForm = withFormik({
  mapPropsToValues: () => ({ email: "" }),
  validationSchema: Yup.object().shape({
    email: Yup.string()
      .email("Invalid email address")
      .required("Email is required!")
  }),
  handleSubmit: (values, { setSubmitting }) => {
    setTimeout(() => {
      console.log(JSON.stringify(values, null, 2));
      setSubmitting(false);
    }, 1000);
  },
})(MyInnerForm);

const App = () => (
  <div className="app">
    <EnhancedForm />
  </div>
);


export default App;


説明内

  1. const MyInnerForm 内の最初の関数...

    • ES6のDestructuringを使用して各値にpropsを代入しています。
    • 中の変数はフォームのStateをpropsとして受け渡す時に使用されます。
    • const MyInnerForm内の各値の中身 Screen Shot 2017-12-11 at 11.11.13.png (257.0 kB)
  2. const MyInnerForm 内のreturn内では...

    • 表示させるコンポーネントを定義しています。
    • inputのclassName内ではフォームがエラー、もしくは選択された時にクラスを変えて事前に定義させたCSSでスタイルを変化させる為のものです。
  3. errorsとtouchedは...

    • どちらも空のオブジェクトを持ったStateです。
    • どちらもvalidationSchemaで定義した文字列を  { email: "文字列" } という形で代入します。
  4. EnhancedForm = withFormikでは....

    • mapPropsToValuesでpropsをvaluesに変換しています。
    • validationSchemaではvalidationの内容を定義しています。
    • handleSubmitではSubmitボタンが押された時のイベントを定義しています。
  5. Yupについて

    • Yupを使用することで簡単にフォームにValidationを使用できます。
Yup.js
// Yupをimportする
var yup = require('yup')

 // schemaで型や入力必須かなどを定義する
var schema = yup.object().shape({
  name:      yup.string().required(),
  age:       yup.number().required().positive().integer(),
  email:     yup.string().email(),
  website:   yup.string().url(),
  createdOn: yup.date().default(function() {
    return new Date
  })
})

 // validationを行う 
schema.isValid({
  name: 'jimmy',
  age: 24
})
.then(function(valid){
  valid // => true
})

handleSubmitでは何が起こっているか

hadnleSubmit.js
handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
   e.preventDefault();
   this.submitForm();
};

  • preventDefaultでブラウザのデフォルトのSubmitイベントが発火しないようにしています。
  • submitForm内では、Formikのvalidateイベントで条件分岐を行いますが、validateは定義されていないので、Yupを使用して定義したrunValidationSchemaイベントが発火します。
  • runValidationSchema内のValidationSchemaは、EnhancedForm内で定義されたテキストを代入します。

おわりに

HighOrderComponentsが苦手なのでもっとドキュメントを読んで
不自由なく扱えるようになりたいです!
補足、間違っている箇所がございましたらご指摘よろしくお願いします。

株式会社VRizeは、VR広告ネットワークやVR動画アプリの制作等、VRに関わる様々なサービスを製作しています。VRとReactに興味があるフロントエンジニアさん、絶賛募集中です!
https://vrize.io/recruits/
https://www.wantedly.com/projects/79383

参考文献

Formik
Yup