takuyahori
@takuyahori (堀 拓也)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

reactでemailjsを利用・バリデーションの判定によりメール送信できるようにしたい

事象

reactにてポートフォリオサイトを作成しており、contactページにてメール送信機能を実装中。emailjsを使用し、送信ができることは確認できましたが、バリデーションの実装をしたところバリデーションの判定に関わらずメールが送信できてしまう事象が発生。
バリデーションの判定でtrueの時のみメールを送信できるようにしたいので、アドバイス頂けますと幸いです。

contactPage.js
import React, { useState } from 'react'
import { send } from 'emailjs-com';

const ContactPage = () => {

  /* input要素内に文字を入力したときの各属性値の空の変数 */
  const initialValues = { name: "", mailAddress: "", message: "" };

  /* 上記の変数に値を格納していくためのuseState。入力するたびテキストが値として変数に格納される。 */
  const [formValues, setFormValues] = useState(initialValues);

    /* 上記の各属性のエラーとそのメッセージ内容を格納するuseState */
  const [formErrors, setFormErrors] = useState({});
  const [ isSubmit, setIsSubmit ] = useState(false);

  /* フォームにテキストが入力されたら */
  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormValues({ ...formValues, [name]: value });
  };

  const sendMail = (e) => {
    e.preventDefault();
    //ログイン情報を送信する前にバリデーションチェック
    /* errorsのuseStateの状態を更新するため。 formValuesに入った値がvalidate関数でエラーかどうか判断される*/
    setFormErrors(validate(formValues));
    setIsSubmit(true);
    
    /* メール送信処理 */
    if(Object.keys(formErrors).length === 0 (
      send(
        'service_cjhg1c8',
        'template_u999xnh',
        { formValues },
        'eWFO3EkLuVxWTVWq5'
      )
    ));
  };

  /* 各項目バリデーションチェック関数 */
  const validate = (values) => {
    const errors = {};
    const regex = /^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]+.[A-Za-z0-9]+$/;
    if(!values.name) {
      errors.name = "名前を入力してください。";
    }
    if(!values.mailAddress) {
      errors.mailAddress = "メールアドレスを入力してください。";
    } else if(!regex.test(values.mailAddress)) {
      errors.mailAddress = "正しいメールアドレスを入力してください。"
    }
    if(!values.message) {
      errors.message = "メッセージを入力してください。";
    }
    return errors;
  };

  return (
    <section className="contact">
      <h1>Contact Form</h1>
      <hr />
      <form className='contact__form' onSubmit={sendMail}>
        <div className='contact__wrap'>
          <div className='contact__left'>
            <div className='contact__field'>
              <label>Name</label>
              <input
                type='text' 
                name='name'
                value={formValues.name}
                onChange={(e) => handleChange(e)}
              />
            </div>
            <p className='contact__error'>{formErrors.name}</p>
            <div className='contact__field'>
              <label>Mail</label>
              <input
                type='text' 
                name='mailAddress' 
                value={formValues.mailAddress}
                onChange={(e) => handleChange(e)}
              />
            </div>
            <p className='contact__error'>{formErrors.mailAddress}</p>
          </div>
          <div className='contact__right'>
            <div className='contact__field'>
              <label>Message</label>
              <input 
                type='text' 
                name='message'
                value={formValues.message}
                onChange={(e) => handleChange(e)}
              />
            </div>
            <p className='contact__error'>{formErrors.message}</p>
          </div>
        </div>
        <div className='contact__send'>
          <button>send</button>
          {Object.keys(formErrors).length === 0 && isSubmit && (
            <div className='content__messageOk'>送信完了しました</div>
          )}
        </div>
      </form>
    </section>
  )
};

export default ContactPage

対象コード

contactPage.js
const sendMail = (e) => {
    e.preventDefault();
    //ログイン情報を送信する前にバリデーションチェック
    /* errorsのuseStateの状態を更新するため。 formValuesに入った値がvalidate関数でエラーかどうか判断される*/
    setFormErrors(validate(formValues));
    setIsSubmit(true);
    
    /* メール送信処理 */
    if(Object.keys(formErrors).length === 0 (
      send(
        'service_cjhg1c8',
        'template_u999xnh',
        { formValues },
        'eWFO3EkLuVxWTVWq5'
      )
    ));
  };

上記で送信ボタンを押したらバリデーションチェックをし、大丈夫ならメール送信を実行という記述をしています。
実際にインプットフォームが空出会ったりメールアドレスに@が含まれていないと赤字でエラー文は出るものの、メールは送信されてしまいます。
formErrorsのオブジェクトに格納したエラー文がなかったらsend実行というつもりで記述しているのですが、うまくいきません、、、

メールは問題なく送れるのでここの条件分岐の記述が問題と考えています。

宜しくお願いいたします。

0

2Answer

ReactのsetState原則非同期です.これはフックでも同様です.
これがどういうことかというとsetFormErrorsを呼び出した段階では formErrorsは更新されません.

現状の実装なら変数に受け取っておくのが良いと思います.

// ...
const err = validate(formValues);
if(Object.keys(err).length > 0) {
  setFormErrors(err);
  return;
}

setIsSubmit(true);
// ...
0Like

Comments

  1. @takuyahori

    Questioner

    アドバイスありがとうございます!
    非同期通信ということ認識不足でした、、、
    おかげさまで解決しました!
    ありがとうございます!

原因については既に回答済みなので、ご紹介
こういったプラグインを使ってエラーチェックをするのも一つの手かと思います
スマートに書けるのでおすすめです

0Like

Comments

  1. @takuyahori

    Questioner

    ご紹介ありがとうございます!
    今後活用してみます!

Your answer might help someone💌