icon

Reactでログインフォームを実装(フロントのみ)

Reactでログインフォームを実装(フロントのみ)
投稿日時

更新日時

YouTubeの「プログラミングチュートリアル」チャンネルの動画を参考に、Reactでログインフォームを作ってみました。今回はフロント部分のみで、バックエンドとのAPI連携はしていません。

ゴールとしては、「ユーザー名」「メールアドレス」「パスワード」を入力し、ログインできるようにします。その際にバリデーションチェックを行い、入力誤りがあればエラーを表示させます。

動画URL

使用技術

React - 18.2.0

HTML

CSS

ファイル構成

- node_modules
- public
- src 
  -- App.css
  -- App.js
  -- index.css
  -- index.js
- packge.json
- gitinore
- yarn.look

全体のコード(App.js)

// App.js

import { useState } from "react";
import "./App.css";


function App() {
  const initialValues = { username: "", mailAddress: "", password: "" };
  const [formValues, setFormValues] = useState(initialValues);
  //配列だと値しか入っていかない。objectならキーと値を入れることができる
  const [formErrors, setFormErrors] = useState({});
  // ログインボタンをクリックしたかどうか
  const [isSubmit, setIsSubmit] = useState(false);


  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormValues({ ...formValues, [name]: value });
    setIsSubmit(true);
  };


  const handleSubmit = (e) => {
    e.preventDefault();
    //ログイン情報を送信する
    //バリデーションチェックをする
    setFormErrors(validate(formValues));
  };


  //どの値をバリデーションチェックするのか→引数が必要
  const validate = (values) => {
    const errors = {};
    const regex =
      /^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/;
    if (!values.username) {
      errors.username = "ユーザー名を入力してください";
    }
    if (!values.mailAddress) {
      errors.mailAddress = "メールアドレスを入力してください";
    } else if (!regex.test(values.mailAddress)) {
      errors.mailAddress = "正しいメールアドレスを入力してください";
    }
    if (!values.password) {
      errors.password = "パスワードを入力してください";
    } else if (values.password.length < 4) {
      errors.password = "4文字以上15文字以下のパスワードを設定してください";
    } else if (values.password.length > 15) {
      errors.password = "4文字以上15文字以下のパスワードを設定してください";
    }
    return errors;
  };


  return (
    <div className="App">
      <form onSubmit={(e) => handleSubmit(e)}>
        <h1>ログインフォーム</h1>
        <hr />
        <div className="uiForm">
          <div className="formField">
            <label>ユーザー名</label>
            <input
              type="text"
              placeholder="ユーザー名"
              name="username"
              onChange={(e) => handleChange(e)}
            />
          </div>
          <p className="errorMsg">{formErrors.username}</p>
          <div className="formField">
            <label>メールアドレス</label>
            <input
              type="text"
              placeholder="メールアドレス"
              name="mailAddress"
              onChange={(e) => handleChange(e)}
            />
          </div>
          <p className="errorMsg">{formErrors.mailAddress}</p>
          <div className="formField">
            <label>パスワード</label>
            <input
              type="text"
              placeholder="パスワード"
              name="password"
              onChange={(e) => handleChange(e)}
            />
          </div>
          <p className="errorMsg">{formErrors.password}</p>
          <button className="submitButton">ログイン</button>
          {/* エラー文の数が0個なら */}
          {Object.keys(formErrors).length === 0 && isSubmit && (
            <div className="msgOk">ログインに成功しました</div>
          )}
        </div>
      </form>
    </div>
  );
}

export default App;


コード解説

onChangeで入力情報を取得する

// App.js 

<div className="formField">
       <label>ユーザー名</label>
            <input
              type="text"
              placeholder="ユーザー名"
              name="username"
              onChange={(e) => handleChange(e)}
            />
</div>

input への入力があった場合、onChange={(e) => handleChange(e)} で入力情報を取得する。

  const initialValues = { username: "", mailAddress: "", password: "" };
  const [formValues, setFormValues] = useState(initialValues);

ReactHooksのuseState を 使用して、inputへ入力された文字列を格納する状態変数を設定する。useStateの初期値は、initialValues のオブジェクトを設定する。

formValues の文字列をinputへ入力されたタイミングで、username へ格納していく必要がある。なので、inputタグにonChange={(e) => handleChange(e)}を設定する。

// handleChange関数  

const handleChange = (e) => {
    const { name, value } = e.target;
    setFormValues({ ...formValues, [name]: value });
    setIsSubmit(true);
  };

inputタグへ入力があるたびに、handleChange 関数が発火して、useState の formValue へ文字列が格納される。

usename ・ mailAddress ・ password を見分ける必要があるため、分割代入を使用し、const {name, value} = e.target でnameとvalueを取得する。

その後、スプレッド構文を使用して、formValuesnamevalue を格納し、 useStatesetFormValues へセットする。


ログインボタンをクリックしたら、ログイン情報を送信する

// App.js

<form onSubmit={(e) => handleSubmit(e)}>

form タグへ onSubmit を設定し、ログインボタンがクリックされる度に、handleSubmit が発火される。

// App.js  

 //配列だと値しか入っていかない。objectならキーと値を入れることができる
 const [formErrors, setFormErrors] = useState({});

const handleSubmit = (e) => {
    e.preventDefault();
    //ログイン情報を送信する
    //バリデーションチェックをする
    setFormErrors(validate(formValues));
  };


e.preventDefault() でクリック時の更新をなくす。

バリデーションチェックするために、空の配列 [formErrors, setFormErrors] を準備して、その中にエラーを格納していく。

オブジェクトにすることで、値だけでなく、キーと値を格納することができる。

setFormErrorsvalidate 関数を呼び出す。

// App.js  

//どの値をバリデーションチェックするのか→引数が必要
  const validate = (values) => {
    const errors = {};
    const regex =
      /^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/;
    if (!values.username) {
      errors.username = "ユーザー名を入力してください";
    }
    if (!values.mailAddress) {
      errors.mailAddress = "メールアドレスを入力してください";
    } else if (!regex.test(values.mailAddress)) {
      errors.mailAddress = "正しいメールアドレスを入力してください";
    }
    if (!values.password) {
      errors.password = "パスワードを入力してください";
    } else if (values.password.length < 4) {
      errors.password = "4文字以上15文字以下のパスワードを設定してください";
    } else if (values.password.length > 15) {
      errors.password = "4文字以上15文字以下のパスワードを設定してください";
    }
    return errors;
  };


複数のパターンを const errors = {} でオブジェクトに格納することで、汎用性が上がる。

(!value.username) ユーザー名に入力がなかった場合。(!value.mailAddress) メールアドレスに入力がなかった場合、また、regex へメールアドレスの正規表現を格納し、正しい表記で入力されなかった場合もエラーを表示させる。

パスワードは、入力がなかった場合と4文字以下の時、15文字以上の時にエラーを表示させる。

ログインに成功したかどうか

//App.js

 // ログインボタンをクリックしたかどうか
 const [isSubmit, setIsSubmit] = useState(false);

 {/* エラー文の数が0個なら */}
 {Object.keys(formErrors).length === 0 && isSubmit && (
      <div className="msgOk">ログインに成功しました</div>
  )}


ログインが成功する条件としては、エラーが0個 かつ ログインボタンをクリックしたか をクリアした時に成功となる。

エラーの keys の数を数えて0個ならOK(エラー文の数)。isSubmit でログインボタンをクリックしたかをチェックするが、初期値は false を設定し、handleSubmit が実行されたときに、true になる。

最後に

今回はログインフォームのフロント部分のみを学習の一環として制作をしました。今後は、バックエンドのAPIと連携させていく方法も学んでいきたいと思います。