Reactプロジェクトにnpmライブラリを導入する流れ【validation編】

### この記事で伝えたいこと
- プロジェクトにおいてコード量を減らし保守しやすくするために、ライブラリを導入するのは非常に重要なことです。作業の時間短縮につながり、チーム人数が増えたとしてもコードを標準化できます。しかしながら、いきなりライブラリを導入したものの要件を満たせないときや、いまいちしっくりこない時もあります。そうなると後戻りするのに時間や余計な手間がかかってしまいます。そのため、この記事では主にReactのプロジェクトにおいて、どのようなアプローチでライブラリを導入すべきか、その考え方と具体的なツールを紹介していきます。

### 今回の記事作成の背景
- 個人開発をチームで行っており、入力フォームのバリデーションやメッセージの表示を自作していました。ですが、今後のやりたいことをピックアプしていくうちに、バリデーションを標準化したい・共通化させて使いやすくしたいという考えが出てきたのでライブラリを導入することに決めました。その過程で知った便利なツールを紹介していきます。また記事の中では具体的なバリデーションのライブラリ名なども紹介していきますが、バリデーションに興味がない方でも、他のライブラリ導入時でも流れやアプローチは同じだと思うので、目次の1,2だけでも読んでいただければ役に立つと思います。

### 解決したい課題
- Reactプロジェクトにおいて、ライブラリの選定方法などがわかる
- 実際のプロジェクトを汚さずに、ライブラリを試し書きできる

### 目次
- 1.使用するライブラリ選定（npm trends）
- 2.実際に書いてみる（code sandbox）
- 3.導入してみたライブラリ

### 1.使用するライブラリ選定
#### 該当するライブラリを探す
- とりあえず、ライブラリの候補を一つでもいいので探すため検索します。今回のバリデーションについてはこちらの記事を参考にしました。( https://bagelee.com/programming/react/validation-library )
- joiが一番歴史が長く人気もあり複雑なこともできるが、ファイルが大きいのがデメリットとのこと。今回はシンプルな実装でいいので軽いファイルの方がいいと思ったので、yupにしようと決めました。このような比較記事がまとまっている場合はあまり困らないですが、比較記事が存在しない場合は次のステップが必要になります。

#### npm trendsで比較する
- npm trends（https://www.npmtrends.com ）とは、npmパッケージ・ライブラリのダウンロード数やスター数を比較できるサイトです。一番ありがたいのは、何か一つのパッケージを入力すると、似たようなパッケージも予測で出てくることです。下記スクショは、検索ボックスに「react」と入力した直後の画面です。angularやvue,svelteなどが表示されてるのが見えます。それらを＋ボタンで追加してあげれば、ダウンロード数やスター数などが比較できます。![スクリーンショット 2021-12-05 8.19.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407898/ebb2d4c0-abcc-bb1b-d54e-eaff83f0256c.png)
- 先ほど選定したyupというライブラリが実際にどれくらい使用されてるのか、似たようなパッケージとの比較をするとどうなのか、下記スクショを残しておきます。
![スクリーンショット 2021-10-23 7.29.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407898/82324ffe-6b8a-f0b2-27d5-39449d569d94.png)
- 見るべきポイントとしては、グラフの「Downloads」と、表の「Stars」「Updated」あたりかなと思います。「Downloads」は、トレンドやどれくらい伸びてるかが確認できます。Starsは人気具合、Updatedはきちんとメンテナンスされてるか、などを確認できます。

#### 記事や公式ドキュメントでコード確認
- Qiita, Zenn, Dev(https://dev.to/ )などで検索して記事数が多いものや、日付が最近の記事があるかを確認します。公式のドキュメントも見ますが、ライブラリ選定の時点では、なるべく広く浅く情報を確認したいので、そこまでがっつりとは見ませんでした。ですが、公式がyoutubeで丁寧に動画をあげてくれているライブラリもあり、その場合はつまった時の助けになるので、ポイントが高いなと思います。

#### 「awesome-xxxx」でもライブラリも探せる
- これはReactに限った話ではないですが、awesome-xxxx と検索すると、xxxに関わるライブラリやパッケージ一覧を表示してるサイトにたどりつけます。
- Reactにおいては、このサイト(https://github.com/enaqx/awesome-react )があるので、ここでライブラリ候補を探し、npm trendsで比較検討という流れでもいいかなと思います。(この情報は後から知ったので今回は使ってなかったです）


### 2.実際に書いてみる
#### code sandbox(https://codesandbox.io/ )を使用
- codesandboxとは、Web上で利用するブラウザIDE、統合開発環境のことです。codesandbox上では、webブラウザ上で簡単にReactの開発環境を構築することができ、githubとの連携などもできます。
- 使い方として、create sandboxボタンを押すと下記スクショ画面が表示されるので、「React Typescript」を選択するとプロジェクトが新たに作成されます。
![スクリーンショット 2021-12-05 8.51.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407898/b4d293b9-1736-c530-dde7-44b01de20a3e.png)
- その後、開発画面に遷移。下記のように左側にソースコード・右側に実行結果が出てきます。
![スクリーンショット 2021-12-05 8.58.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407898/d9aa0e01-29c1-73d3-d7e9-66b8a52dc29c.png)

- またnpmパッケージもGUIで簡単にインストールできるので非常に便利です。プロジェクト作成後、
左下のDependencies直下の検索ボックスからライブラリを選択すればそのままインストールできます。
![スクリーンショット 2021-10-23 7.44.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407898/d54da5b7-2d3a-3b53-cbcc-4b0367964b46.png)
- なお、使い方や詳細はこの記事がわかりやすかったです。
  - https://freelance-jak.com/technology/react/1106/
  - https://qiita.com/nishiurahiroki/items/279041447ef1415804c2

- このcodesandboxで下書きをしてみるメリットとしては、手元の開発環境を汚さずに試し書きができるという点だと思います。
- また、公式のチュートリアルや技術記事に書かれてるコードはシンプルに書かれているので、実際のプロジェクトのアーキテクチャが複雑だった場合はそこにあてはめないといけないので、思い通りに実装ができない時もあります。なので、codesandbox上で試しに書くときに、プロジェクトにあわせた構成を先に書くことをオススメします。
- 今回は、先にyupというバリデーションライブラリをこのcodesandbox上で試した結果、このライブラリだけだと実装したい要件に満たなかったので、追加でフォームのライブラリを探すことになりました。
- もし、ここまでで検証が十分にできていれば、実際のプロジェクトに実装は出来るかなと思います。

### 3.今回導入してみたライブラリ
#### 採用したライブラリ（結論）
- yup (validation系)
- formik (Form系)

#### 調査過程
- yupだけだと、入力値の判定のみしか返却できません。これは先ほどのcodesandboxで動きを見て確認ずみです。しかし判定だけでなくエラーメッセージの表示もしてほしかったのですが、そのためにはフォーム系のライブラリをいれる必要であることがわかりました。
- よくあるパターンとして、yup + αのライブラリという感じでした。そしてその+αにあたるのが、formik と react-hook-form であり、これらがフォーム系ライブラリの２トップという感じでした。
![スクリーンショット 2021-12-05 9.47.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407898/a385192c-6946-7d65-bdc8-516cf71bd3ac.png)
- youtube・qiita・zennなどの情報が豊富そうで、公式がyoutube動画も出していてわかりやすいので、今回はformikで実装しました。
- 主に参考にした、技術記事や動画をはっておきます
  - https://dev.to/youssefzidan/getting-started-with-react-formik-yup-j49
  - https://www.youtube.com/watch?v=DZiltZH1-d0
  - https://www.youtube.com/watch?v=PpdXB9Ru6oI&list=PLC3y8-rFHvwiPmFbtzEWjESkqBVDbdgGu&index=12
- なおreact-hook-formは公式ドキュメントが日本語訳されてるので、こちらのライブラリでも問題はなかったと思います。

#### 実装する上で時間がかかった箇所
- 今回はある程度プロジェクトがすすんだ状態でライブラリを導入したので、どこまでライブラリに合わせた書き方にするかというのが大変でしたし、そもそも動く状態にもっていくのに時間がかかってしまいました。
- Formikのドキュメントに合わせた書き方にするには、コードを大幅に変更する必要があります。また、開発者が自分だけではないのであまりに大掛かりに変更してしまうと、変更後のコードを読む人も大変です。そのため、最小限の変更で動かせるように心がけました。
- 具体的に時間がかかった・つまってしまった箇所は、値を変更する箇所です。

```javascript

const [val, setVal ] = useState("type")
...

return (
...
<input
value = {val}
onChange = {setVal(e.target.value)} >
...
)

```

- 上記のようなコードがあった場合、`onChange = {handleChange}`と書くのがformikにおける書き方ですが、今回はプロジェクトでは、validation schemeを定義している箇所と、値を入力するinputボックスが書かれているファイルが異なっていました（親と子のコンポーネントにわかれている）のが原因なのか、handleChangeがきちんと動作しませんでした。
- このような場合には、親コンポーネントから、子コンポーネントにformikを継承してきたうえで、`onChange{formik.setFieldValue(field, e.target.value)}`とすることで動作するようになりました。
- 詳細は下記記事を参考にしました。
 - https://formik.org/docs/guides/validation#when-does-validation-run
 - https://qiita.com/Hitomi_Nagano/items/424ef83dba427bd0b2b8
- 今回の実装はプロジェクトの構成に合わせた内容になっており、もう少しいい方法もあるのでは？と考えています。今のプロジェクトは後々リファクタリングをしていく予定なので、よりよい方法が見つかった場合は別記事にまとめていきたいと思います。
- また、間違いなどがあればご連絡いただければ幸いです。