0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】ログイン画面を実装してみた!

0
Last updated at Posted at 2025-12-24

やりたいこと

導入

  • 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の階層

結果

スクリーンショット 2025-12-25 061230.png

感想

  • 特に詰まることなく4時間くらいで完成させられた
  • 実装の順番は,HTML→CSS→React→CSSだった
  • サーバー系の言語と組み合わせて,より本格的なログイン画面にしたい

その他

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?