Formikで基本的なフォームを実装してみた

Reactのフォームライブラリ「Formik」を使用し、基本的なフォームの実装方法についてまとめました。

今回実装するのは、以下のフォームになります。

![画面収録-2020-12-30-14.21.00.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584128/0c38e3f4-b518-b965-f90c-6b73c2ef75f7.gif)

まずはライブラリのインストールをして下さい。
formik公式が推奨しているバリデーションライブラリ「yup」も一緒にインストールします。

```
npm install formik yup --save
```

▼ 全体コード（※cssは省いています）

```react
import React from 'react'
import { Formik, Form, Field } from 'formik'
import * as Yup from 'yup'

const Top = () => {
  return (
    <Formik
      initialValues={{
        name: '',
        profession: '',
        sex: '',
        hobby: '',
      }}
      validationSchema={Yup.object().shape({
        name: Yup.string()
          .required('氏名を入力してください。')
          .max(10, '10文字以下で入力してください。'),
        profession: Yup.string().required('職業を選択してください。'),
        sex: Yup.string().required('性別を選択してください。'),
        hobby: Yup.array().required('趣味を選択してください。'),
      })}
      onSubmit={(values) => console.log(values)}
    >
      {(props) => {
        const { errors, touched } = props
        return (
          <Form>
            <div>氏名</div>
            <Field
              name="name"
              type="text"
              placeholder="氏名を入力してください"
            />
            {errors.name && touched.name && (
              {errors.name}
            )}

            <div>職業</div>
            <Field name="profession" as="select" >
              <option>ー</option>
              <option value="公務員">公務員</option>
              <option value="経営者・役員">経営者・役員</option>
              <option value="会社員">会社員</option>
              <option value="アルバイト">アルバイト</option>
              <option value="学生">学生</option>
              <option value="その他">その他</option>
            </Field>
            {errors.profession && touched.profession && (
              <div>{errors.profession}</div>
            )}

            <div>性別</div>
            <label>
              <Field name="sex" type="radio" value="男性" />
              男性
            </label>
            <label>
              <Field name="sex" type="radio" value="女性" />
              女性
            </label>
            {errors.sex && touched.sex && (
              <div>{errors.sex}</div>
            )}

            <div>趣味</div>
            <label>
              <Field name="hobby" type="checkbox" value="音楽" />
              音楽
            </label>
            <label>
              <Field name="hobby" type="checkbox" value="映画" />
              映画
            </label>
            <label>
              <Field name="hobby" type="checkbox" value="読書" />
              読書
            </label>
            {errors.hobby && touched.hobby && (
              <div>{errors.hobby}</div>
            )}

             <button type="submit">
               送信
             </button>
          </Form>
        )
      }}
    </Formik>
  )
}

export default Top

```

formikを使用することで、バリデーション含めこれだけの記述でフォームを実装することができます。

ここからは、各処理について一つずつ説明していきます。

### initialValues
```react
initialValues={{
  name: '',
  profession: '',
  sex: '',
  hobby: '',
}}
```
こちらで各値の初期値を設定することができます。

今回作成するフォームでは、

- 氏名=name
- 職業=profession
- 性別=sex
- 趣味=hobby

とし、初期値は空に設定しています。

### validationSchema
```react
validationSchema={Yup.object().shape({
  name: Yup.string()
    .required('氏名を入力してください。')
    .max(10, '10文字以下で入力してください。'),
  profession: Yup.string().required('職業を選択してください。'),
  sex: Yup.string().required('性別を選択してください。'),
  hobby: Yup.array().required('趣味を選択してください。'),
})}
```

各項目のバリデーションの記述になります。

formikが推薦しているバリデーションライブラリ「yup」を使用することで、このようにコンパクトにバリデーション処理を記述することができます。

今回のフォームでは、氏名に対しては必須と10文字以下、他項目に対しては必須のバリデーションを付与しています。

yupでは他にも便利な記述がたくさんあるので以下から参照してみてください。
https://github.com/jquense/yup


### onSubmit
```react
onSubmit={(values) => console.log(values)}
```
submitボタンが押された時に、どのような処理を行うか記述する関数です。
バリデーションが全て通った場合のみ処理を行う関数なのでご注意ください。

今回はデモのため、consoleにデバッグさせる処理のみ記述していますが、
ほとんどの場合は、こちらでAPIを叩く実装を記述することになります。

valuesには、initialValuesで設定したパラメータが格納されています。

### Field
```react
<Field
  name="name"
  type="text"
  placeholder="氏名を入力してください"
/>
```

formikでは、inputの代わりにFieldコンポーネントを使用します。

nameに対してパラメータの値を設定することで、formikのvaluesにリアルタイムで反映させることができます。

![画面収録-2020-12-30-16.05.04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584128/70ca82a7-1e66-e5bd-e48c-8f0263ffcf24.gif)

### errors
```react
{errors.name && touched.name && (
  <div css={errorTxt}>{errors.name}</div>
)}
```
formikではerrorsとtouchedがpropsとして用意されており、リアルタイムにバリデーションを表示させることができます。

errors：validationSchemaで設定したバリデーション比較、文言表示
touched：入力エリアにカーソルがクリックされたかどうかを判定

こちらの処理では、errorsが存在しtouchedがtrueの場合のみバリデーションエラーを表示させるよう設定しています。

## 終わりに
formikでは様々なコンポーネントやメソッドが備わっており、より柔軟なフォームの実装が可能となっております。

今回はformikの基本的な動作の説明でしたが、次回は応用的なformikの使用方法について説明したいと思います。

もしreactのフォームライブラリで悩んでいる方がいましたら、是非一度formikをお試し下さい！