React入門 - Part9 - formikとyup(値の保持、バリデーション)

<!-- https://qiita.com/macotok/items/df1fdcac02e64638d9c8 -->

<!-- https://suwaru.tokyo/%E3%80%90formik-yup%E3%80%91react%E7%B0%A1%E5%8D%98%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E4%BD%9C%E6%88%90%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E8%A7%A3%E8%AA%AC/ -->

<!-- https://codezine.jp/article/detail/13226 -->

# 目次
[React入門](https://qiita.com/yokowake12345/items/0919ad144cbc4684e64e)

# formikとyupについて

formikは、Reactでよく使われる入力支援ライブラリです。
私が携わったプロジェクトでは、フォーム入力項目の値保持のために使用していました。

yupは、バリデーション用ライブラリ。formikのみでもバリデーションを実装できるようですが、JavaScriptでスキーマ（データ構造）を定義するためのライブラリである、ということらしいです。
つまり、バリデーションを定義体で宣言し利用できるということでしょう。

<font color="red">※Part9ということになっていますが、Part5くらいの位置付けですね。</font>
React入門全部書き終えたら入れ替えたいと思います。

# インストール

[Part2](https://qiita.com/yokowake12345/items/132fbd4129afd9b37500)の環境設定を終えたら、プロジェクトディレクトリで下記を実行しformikをインストール

```typescript
npm i formik
```

yupをインストール

```typescript
yarn add yup
```

上記２つは

```typescript
yarn add formik yup
```

でもいいみたいですね。

# コーディング(formik)

```typescript
import React, {useState, useLayoutEffect} from 'react';
import { useFormik } from 'formik';

export const FormikTest: React.FC = () => {
    // formikの定義
    const formik = useFormik({
      // 初期値の定義　　
      initialValues: {
        id: 'yokowake',
        pwd: '',
      },
      // サブミット時の処理を記述
      onSubmit: (values) => {
        console.log('form data', values);
      },
    });

    /** レンダー部分 */
    return (
      <div>
        <form>
          <div>
            <label htmlFor="id">Id</label>
            <input
              type="text"
              id="id"
              name="id"
              onChange={formik.handleChange}
              value={formik.values.id}
            />
          </div>
          <div>
            <label htmlFor="pwd">Pwd</label>
            <input
              type="text"
              id="pwd"
              name="pwd"
              onChange={formik.handleChange}
              value={formik.values.pwd}
            />
          </div>

          <button onClick={() => formik.handleSubmit()}>Submit</button>
        </form>
      </div>  
    );
};

export default FormikTest;
```

以下でアクセスすると、初期値が表示されていますね。
また、Submitボタンクリックするとコンソールに入力値が出力されていることが確認できると思います。

```
localhost:3000/formik-test
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559029/b98444f1-d5ef-a864-0d2e-81a43a09694e.png)

# コーディング(yup)

上記ソースに加え、バリデーションを実装してみます。

```typescript
import React, {useState, useLayoutEffect} from 'react';
import { useFormik } from 'formik';
import * as Yup from "yup";  // yupをimport

export const FormikTest: React.FC = () => {

  // ★☆★☆入力チェックスキーマ
  const validationSchema = 
    Yup.object({
      id: Yup.string()
        .required("idは必須項目です"),
      pwd: Yup.string().required("パスワードは必須項目です")
    });

  // formik定義
  const formik = useFormik({
      // 初期値の定義
      initialValues: {
        id: 'yokowake',
        pwd: '',
      },
      // ★☆★☆バリデーション定義
      validationSchema,
      // サブミット時の処理を記述
      onSubmit: (values) => {
        alert('form data : ' + JSON.stringify(values))
      },
    });

    /** レンダー部分 */
    return (
      <div>
        <form onSubmit={formik.handleSubmit}>
          <div>
            <label htmlFor="id">Id</label>
            <input
              type="text"
              id="id"
              name="id"
              onChange={formik.handleChange}
              value={formik.values.id}
            />
            {/* ★☆★☆エラー表示 */}
            {formik.touched.id && formik.errors.id ? (
              <div className="error">
                <span style={{color: 'red'}}>{formik.errors.id}</span>
              </div>
            ) : null}
          </div>
          <div>
            <label htmlFor="pwd">Pwd</label>
            <input
              type="text"
              id="pwd"
              name="pwd"
              onChange={formik.handleChange}
              value={formik.values.pwd}
            />
            {/* ★☆★☆エラー表示 */}
            {formik.touched.pwd && formik.errors.pwd ? (
              <div className="error">
                <span style={{color: 'red'}}>{formik.errors.pwd}</span>
              </div>
            ) : null}
          </div>
          {/* サブミットボタン */}
          <button onClick={() => formik.handleSubmit()}>Submit</button>
        </form>
      </div>  
    );
};

export default FormikTest;
```

**<font color="red">formikの定義とnameプロパティを一致させて実装します。</font>**

動作確認してみてください。
必須チェックが実装できたことが確認できると思います。
必須チェック以外にも桁数チェックなどを実際は実装していくかと思います。
属性チェックなども。
詳しくはyupなどでググってみてください。

以上