やりたいこと
- こちらを参考にして実装
導入
- Reactの環境構築をしていない場合はこちらを参照
$ conda create -n react python=3.11
$ conda activate react
$ npm create vite@latest my-app
$ cd my-app
実装
App.jsx
import { useState } from "react"; /*追加*/
import "./App.css";
function App() {
/*入力内容を保持する処理を書く*/
const initialValues = { userName: "", mailAddress: "", passWord: ""}; // initialValues;空のオブジェクトを用意
const [formValues, setFormvaluese] = useState(initialValues); // 入力値をinitialValuseに格納 // useState;入力状態を示す
const [formErrors, setFormErrors] = useState({}); // オブジェクト(key:value)を格納
const [isSubmit, setIsSubmit] = useState(false); // ログインボタンが押されていない状態
const handleChange = (e) => { /*inputの内容(e;イベント)を受け取る*/
// console.log(e.target); /*debag用;検証のconsoleでinput属性が受信した内容を確認可能, .valueを付けると文字列を確認可能*/
const { name, value } = e.target;
setFormvaluese({ ...formValues, [name]: value }); // formvalues;initialValuesの初期値が入る, name;e.targetで取得したname属性(username), value;入力された文字列
// console.log(formValues); // 入力情報を保持してるか確認
};
const handleSubmit = (e) => {
e.preventDefault(); // ログインを押した時のリロード防止
// ログイン情報を送信
setFormErrors(validate(formValues)); // validationCheck用
setIsSubmit(true) // ログインボタンが押された場合
};
const validate = (values) => {
const errors = {}; // userName, mailAddress, passWordのどこでエラーが出たかを特定するためにエラーを格納
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 < 8) {
errors.passWord = "*8文字以上15文字以内で入力して下さい. ";
} else if (values.passWord.length > 15) {
errors.passWord = "*8文字以上15文字以内で入力して下さい. ";
}
return errors;
};
/*ここまで*/
return (
<div className="formContainer"> {/*loginForm内の大枠*/}
<form onSubmit={(e) => handleSubmit(e)}> {/*ログイン処理用*/}
<h1>ログイン</h1>
<hr /> {/*長い横線を引く*/}
<div className="uiForm"> {/*loginForm内の中枠, ログインフォームの枠*/}
<div className="formField"> {/*loginForm内の小枠*/}
<label>ユーザー名</label>
<input /*ユーザ入力欄*/
type="text"
placeholder=""
name="userName" /*name属性付与*/
onChange={(e) => handleChange(e)} /*handleChangでuseStateの中に入力値を格納*/
/>
</div>
<p className="errorMsg">{formErrors.userName}</p> {/*erro内のオブジェクトのkeyを指定,対応するvalueを出力*/}
<div className="formField"> {/*小枠*/}
<label>メールアドレス</label> {/*css用にlabelタグを付与*/}
<input
type="text"
placeholder="" // ユーザ入力欄
name="mailAddress" // name属性付与
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="loginButton">ログイン</button>
{Object.keys(formErrors).length === 0 && isSubmit && (
<div className="msgOk">ログインに成功しました!</div>
)} {/*formErrors内にkey(userName等)が格納されていない場合*/}
</div>
</form>
</div>
);
}
export default App;
App.css
/*css gradientで背景にグラデーションを指定可能*/
body {
background: #833AB4;
background: linear-gradient(
90deg, rgba(131, 58, 180, 1) 0%,
rgba(253, 29, 29, 1) 50%,
rgba(252, 176, 69, 1) 100%
);
overflow: hidden; /*スクロール部分を隠す*/
}
.formContainer {
height: 100vh;
width: 100%;
display: flex;
align-items: center; /*画面縦に対して中央*/
justify-content: center; /*画面横に対して中央*/
}
.formContainer form { /*ログイン画面の大枠*/
background-color: rgb(253, 253, 253);
width: 100%; /*画面横に対して70%*/
height: 100%;
max-width: 300px; /*横幅の最大値を500に制限*/
max-height: 350px;
padding: 30px; /*上下左右30px空ける*/
border-radius: 10px; /*角丸*/
box-shadow: 22px 24px 16px -11px #3e3e3e; /*cssボックスシャドウジェネレーターで影を付与*/
font-size: 15px; /*ログイン文字のサイズ*/
/*background-color: aquamarine;*/
}
.uiForm { /*ユーザ名からボタンまでの範囲*/
display: flex; /*項目を横並びに統一*/
flex-direction: column; /*項目を縦並びに統一*/
align-items: center; /*横に対して中央*/
justify-content: space-evenly;
/*background-color: #833AB4;*/
}
.formField { /*入力欄を縦並びにする処理*/
display: flex; /*項目を縦並びに統一*/
flex-direction: column; /*項目を縦並びに統一*/
width: 100%; /*uiForm(親)に対して100%*/
}
.formField input{ /*入力欄*/
border: 1px solid grey;
padding: 1px; /*上下左右に空白*/
font-size: 20px;
border-radius: 6px; /*角丸*/
}
.formField input:focus { /*入力欄の枠が黒化を防止*/
outline: none;
}
.formField label { /*ユーザー名等の項目*/
font-size: 15px;
font-weight: 600; /*太文字*/
margin-bottom: 3px; /*下に空白*/
}
button { /*.付けない!*/
background-color: #9900ff;
width: 30%; /*uiFormに対して*/
margin-top: 15px; /*ボタンの上に空白*/
border: none; /*枠線削除*/
border-radius: 5px;
padding: 5px; /*ボタンの幅を調整*/
color: white;
font-size: 15px; /*ボタンの文字サイズ*/
cursor: pointer; /*ボタン上で矢印が指に変化*/
transition: all 0.2s; /*フワッと色を変える*/
}
button:hover {
background-color: #7900ca;
}
.errorMsg {
color: red;
margin: 0; /*余計な隙間を埋める*/
align-self: flex-start; /*左寄せ*/
}
.msgOk {
color: rgb(0, 0, 0);
margin-top: 10px;
}
実行
$ npm run dev # my-appの階層
結果
感想
- 特に詰まることなく4時間くらいで完成させられた
- 実装の順番は,HTML→CSS→React→CSSだった
- サーバー系の言語と組み合わせて,より本格的なログイン画面にしたい
その他
