React-hook-formとEmailJSで簡単にメールが送れるフォームを作ってみた

## 概要
個人開発の[QuickURL](https://quick-url-b0462.web.app/)を作っている時に、なるべく簡単に送れるフィードバックのフォームを作ろうと考え、「利用者さんがテキストエリアに入力して送信するだけで僕のメールに文章が届く」仕組みを作りました✨

今回はReact-hook-formとEmailJSを使用します

自分も初心者なので、なるべくわかりやすく書きました🔥
順番に読んでいただければ使い方が分かるはずです！
## React-hook-formでフォーム作成
この機能を作る際はReact-hook-formで入力フォームを作成し、EmailJSで送信機能を作成します
まずはReact-hook-formでフォームを書いていきます

### ①準備
```bash
// npmの場合
npm install react-hook-form

// yarnの場合
yarn add react-hook-form
```
最初にreact-hook-formをインストールして…
```jsx
import { useForm } from "react-hook-form";
..............................................
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();
```
このように基本的なインポートを行ってください
そうしたら実際にformを作っていきます

---

### ②実際に書いてみる
React-hook-formでは基本的な書き方は素のHTMLのような記載で、そこにバリデーションやエラーへの対応を書き足していく形です。
今回は簡単なフィードバック用ということで一つのテキストエリアと一つのボタンを作成します

まずはただのHTMLではこんな感じ↓
```jsx
<form>
   <textarea />
   <input type="submit" />
</form>
```
これにReact-hook-formでの設定を追記するとこんな感じ↓
```jsx
<form onSubmit={handleSubmit((data) => console.log(data))}> ←-1つ目の追記ポイント!
   <textarea {...register("feedback", { required: true })} /> ←-2つ目の追記ポイント!
   {errors.feedback && <p>文字を入力してください</p>} ←-3つ目の追記ポイント!
   <input type="submit" />
</form>
```
追記した三つの部分について解説します
説明が伝わりやすいように、2つ目、1つ目、3つ目の順番で追記ポイントを解説しますね

---

#### textareaの{register....}の中の部分について👾
```jsx
<form onSubmit={handleSubmit((data) => console.log(data))}>
```
これは、その入力フォームの「名前」と「バリデーション」を設定しています

register関数の第一引数にstring型で名前を設定し、第二引数にobject型でバリデーションを設定します。上の例ではrequiredという項目の設定のみですが、実際には以下のように様々な設定があります

:::details register関数の設定
| 項目 | 型 | 説明 |
| ---- | ---- | ---- |
| required | boolean | フィールドが必須であるかどうかを示します |
| min/max | number / string / Date | フィールドの最小値または最大値を示します |
| minLength/maxLength | number | フィールドの最小文字数または最大文字数を示します |
| pattern | RegExp | フィールドの値がマッチする必要がある正規表現パターンを示します。正規表現オブジェクトで指定します |
| validate | Fuction | カスタムバリデーション関数を指定します。関数はフィールドの値を引数として受け取り、バリデーションの結果を返します |
:::

registerというのは登録を意味する単語で、それぞれのフォームについてReact-hook-formが理解できるように登録しているということですね

#### onSubmit部分について👾
```jsx
<textarea {...register("feedback", { required: true })} />
```
これは、送信されたときにhandleSubmitというReact-hook-formで提供されている関数を実行するようにしています。(この関数は全てのフォームが上記で指定したregisterの条件に違反していない場合のみ実行)

引数のdataはオブジェクトで、それぞれの入力フォームの名前と入力された文章が格納されます
*{ feedback, "ここに入力された文章" }*

この部分ではconsole.log(data)でデータをコンソールに表示させているだけですが、実際にはこのデータを送信するなどの処理を行うでしょう

#### {errors....}と書いている部分について👾
```jsx
{errors.feedback && <p>文字を入力してください</p>}
```
これは「errors.〇〇〇」の〇〇〇部分にフォームの名前を書くことによって、送信時にそのフォームがregisterで登録した条件に従っているか否かのbooleanを取得します

そのため上記の例ではfeedbackにrequiredをtrueとして設定しているので、もし文字を入力せずに送信したら、「<p>文字を入力してください</p>」が出力されるようになっています

{}に処理として書いているだけなので、実際にはファイル内のどこに書いても問題はありません

### ③フォームは完了
これでReact-hook-formでのフォーム作成は完了しました！
フォームのバリデーションなどが実現したかった方はここまでで大丈夫です

ここで入力した内容をメールに送信できるようにしたい方は続きのEmailJSの部分までご覧ください

## EmailJSでメール送信機能を作る
ここからはEmailJSの使い方についてまとめます
EmailJSについて徹底的に解説している記事などは既にあるのですが、今回はReact-hook-formと連動して送信機能を作る方法を解説します💫

これは今までのReact-hook-formの設定よりはるかに簡単なので安心してください！
### ①まずはEmailJSへの登録と準備
EmailJSを使うためにはまず登録をしなければなりません
[EmailJS](https://www.emailjs.com/)にアクセスして、画面右上からアカウント作成してください
![](https://storage.googleapis.com/zenn-user-upload/491ad02b1b15-20230522.png)
そしてログインすることができたら、ダッシュボードからserviceとtemplateを作成していきます

#### serviceの作成
![](https://storage.googleapis.com/zenn-user-upload/ad547c83e9a0-20230524.png)
「Add New Services」を押してGmailを押すと上記のような画面になります
nameには何らかの適切な名前を設定(僕の例だとQuickURLFeedback)して
「Connect Account」にメールを受け取りたいアカウントを設定してください

#### templateの作成
![](https://storage.googleapis.com/zenn-user-upload/fe779869e6c5-20230524.png)
「Create New Template」を押すと上記のような画面になります
名前は任意のものにしてください

重要なのは{{message}}と書かれている部分です！
この部分をreact-hook-formで設定したdataの名前と一致させておく必要があります

dataの名前というのはregisterの第一引数で登録した部分にあたるため、今回の例だと「feedback」になります
```jsx
<Textarea{...register("feedback", { required: true })}/> //この「feedback」の部分
```
僕は以下のようにしています
以下のようにすると「フォームから送信した内容のみがメールに格納される」ようになります
![](https://storage.googleapis.com/zenn-user-upload/f46e6d0b2570-20230524.png)

---

これでEmailJS側で行う作業は終了です

### ②環境変数にIDを追加する
serviceとtemplateを作ったので、ServiceIDとTemplateIDを使うことができます
これらのIDとPublic Keyを合わせた三つのIDで送信機能を作ります

ServiceIDとTemplateIDはそれぞれに分かりやすく書いているので、すぐ見つかると思います
Public KeyはAccountというセクションの一番上に書いています

これら3つのIDを見つけることができたら、実際にコードに書いていくのですが、これらは秘密にしておくべきIDなのでsrc内に直接書くべきではありません

なので.envファイルを作成して環境変数として使います

---

では実際に環境変数に追加します
ここから説明する手順は一見難しく見えますが、実はとても簡単でした


#### .envファイルを作る
プロジェクトのルートディレクトリに「.env」という名前のファイルを作ってください。その後そのファイル内に以下のようにIDを格納していきます
```jsx
REACT_APP_EMAILJS_SERVICE_ID=ここにServiceID
REACT_APP_EMAILJS_TEMPLATE_ID=ここにTemplateID
REACT_APP_EMAILJS_PUBLIC_ID=ここにPublicKey
```
IDを入れるときは''(クォーテーション)などは書かないで大丈夫です！
#### gitignoreに追加する
先ほども言いましたがこのIDは人に見せるべきものではないので、githubにアップしてしまうと困ります

なのでgitignoreというファイルに.envという文字を追加してください
```jsx
////////
.env.test.local
.env.production.local
.env //←これを追加するだけです！！！！

npm-debug.log*
yarn-debug.log*
////////
```
これで環境変数の追加はOKです！
## react-hook-formとEmailJSの連携
ここまでで、それぞれのツールの下準備は終わりました
もう8割の作業は手順は終了です

後は二つのツールを連携してメールを受け取れるようにしましょう！

### ①送信時の関数の作成
実際にformがsubmitされたときにEmailJSに内容を送ることができるように、submit時の関数を作る必要があります

react-hook-formにおいてはsubmit時に入力された情報をもって処理するためにhandleSubmitという規定の関数を使います。これの引数として実際の関数を書いていく形です
(このような形式をとっている理由は後ほど解説します)

今回はsubmitMailという名前の関数にしてみます

```jsx
const submitMail = () => {} // ←-追記ポイント

<form onSubmit={handleSubmit(submitMail)}> // ←-追記ポイント
   <textarea {...register("feedback", { required: true })} />
   {errors.feedback && <p>文字を入力してください</p>}
   <input type="submit" />
</form>
```
次のセクションからは関数の中身を書いていきます
### ②環境変数を受け取る
先ほども言いましたが、EmailJSにメールを送信するためには3つのIDが必要です
前のセクションで設定した環境IDを受け取って使用しましょう
```jsx
const submitMail = () => {
    const serviceId = process.env.REACT_APP_EMAILJS_SERVICE_ID;
    const templateId = process.env.REACT_APP_EMAILJS_TEMPLATE_ID;
    const publicId = process.env.REACT_APP_EMAILJS_PUBLIC_ID;
}
```
このようにすることで3つのIDを定義出来ました
### ③この関数の引数について
react-hook-form特有の関数であるhandleSubmitの引数として実行した関数は、入力フォームのデータを引数として受け取ります

つまりこのsubmitMailは引数として入力データのオブジェクトを受け取れるのです。これがhandleSubmitという関数を使う記述を行った理由でした

今回の例では引数で以下のようなオブジェクトを受け取ります
```jsx
{feedback: 'ここに入力された文字'}
```
registerで名前をfeedbackに設定しているから、このデータでのプロパティもfeedbackなのですね
### ④ついにメールを送信
これで「送信先の特定のためのID」と「送信する内容の取得」が整いました
ということでメールを送信するロジックを書くことができます！

EmailJSに送信するにはemaijs.send()の関数を使います
この関数には4つの引数を入れる必要があり、以下のようにする必要があります
```jsx
emailjs.send(serviceId, templateId, 'ここにメールのデータ', public_Id);
```
ということでこれらの内容を踏まえて実際にメール送信のコードは以下のようになります
```jsx
  const submitMail = async (data) => {
    const serviceId = process.env.REACT_APP_EMAILJS_SERVICE_ID; //ServeceIDを取得
    const templateId = process.env.REACT_APP_EMAILJS_TEMPLATE_ID;// TemplateIDを取得
    const publicId = process.env.REACT_APP_EMAILJS_PUBLIC_ID; // Public Keyを取得
    
      try {
        await emailjs.send(serviceId, templateId, data, publicId);
      } catch (error) {
      console.error("エラーが出ました" + error)
      }
    }
  };
```
これはいたって単純なtry-catch文で書かれています
要は「送信にtryします。もし失敗したらcatch内の処理を行います」ということです

肝心の送信部分については三つのIDによって送信先を指定し、データ部分には引数のdataを格納しました

これでメールの送信機能が完了しました。フォームに文章を入力して送信すると、あなたのメールにその文章が届きます！![](https://storage.googleapis.com/zenn-user-upload/3d8b262d8149-20230526.png)
## まとめ
中々に長い手順でした。お疲れさまでした！
この量の技術記事を書いたのは初めてなので、わかりにくかった所があれば申し訳ないです

普段は沢山の人に使われるサービスを個人開発することを目標に頑張っていますので、少しでも応援しようと思ってくれた方は[Twitter](https://twitter.com/sotetu79)や[QuickURL](https://quick-url-b0462.web.app/)をチェックしてもらえると嬉しいです！

ありがとうございました☆