YouTubeの「プログラミングチュートリアル」チャンネルの動画を参考に、Reactでログインフォームを作ってみました。今回はフロント部分のみで、バックエンドとのAPI連携はしていません。
ゴールとしては、「ユーザー名」「メールアドレス」「パスワード」を入力し、ログインできるようにします。その際にバリデーションチェックを行い、入力誤りがあればエラーを表示させます。
使用技術
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を取得する。
その後、スプレッド構文を使用して、formValues へ name と value を格納し、 useState の setFormValues へセットする。
ログインボタンをクリックしたら、ログイン情報を送信する
// 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] を準備して、その中にエラーを格納していく。
オブジェクトにすることで、値だけでなく、キーと値を格納することができる。
setFormErrors で validate 関数を呼び出す。
// 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と連携させていく方法も学んでいきたいと思います。