Genie

学んだ事

reactでログインフォーム作成

 

1.Reactでログインフォームを作成する方法

githubに完成形があります。

github.com

環境
node 20.11.1

npm 10.4.0


mkdir login-formと空のフォルダを作成し、cd login-formにディレクトリ移動

create-react-app login-form
と入力しreactの雛形を作成します。


概要としては、ログインフォームをHTMLタグで作成し、
ユーザー名、メールアドレス、パスワードは<div>タグで作成します。
その下にログインボタンを設置し、
最後にログインに成功しましたのpタグを用意します。
そしてそれぞれのdivタグの中にlabelが存在し、inputタグを作成します。

 

1.HTMLの雛形を作成

src/App.jsをこのように編集します。

import './App.css';

function App() {
  return (
    <div className="formContainer">
      <form>
        <h1>ログインフォーム</h1>
        {/* <hr /> #横線を引くタグ# */}
        <hr />
        <div className="uiform">
          <div className="formField">
            <label>ユーザー名</label>
            <input type="text" placeholder="ユーザー名" name="username" />
          </div>
          <div className="formField">
            <label>メールアドレス</label>
            <input type="email" placeholder="メールアドレス" name="email" />
          </div>
          <div className="formField">
            <label>パスワード</label>
            <input type="password" placeholder="パスワード" name="password" />
          </div>
        </div>
      </form>
    </div>
  );
}

export default App;
 

npm startでローカルサーバーを立ち上げるとこのようなフォームになります。
次にdivタグの下にログインボタンを作成します。
 
          </div>
        </div>
        <button className="submitButton">ログイン</button>
      </form>
    </div>

このようにログインボタンが追加され、HTMLの雛形の作成が終わりました。
 

2: CSSの雛形作成

それではsrc/App.cssを一回初期化し、
bodyに
body {
  background: rgb(0,249,255);
  background: linear-gradient(90deg, rgba(0,249,255,1) 0%,
 rgba(2,155,156,1) 85%, rgba(0,212,255,1) 100%);
  overflow-y: hidden;
}

.formContainer {
  height: 100vh;
}
と入力します。
bodyの背景色はCSS Gradientで

cssgradient.io

を使いました。

overflow-y: hiddenに解説ですが、height: 100vhで高さを合わせるとwebページがスクロールできてしまうので、はみ出た分を隠す為のプロパティを入力します。

そうしましたら、.formContainerを編集します。

body {
  background: rgb(0,249,255);
  background: linear-gradient(90deg, rgba(0,249,255,1) 0%,
  rgba(2,155,156,1) 85%, rgba(0,212,255,1) 100%);
  overflow-y: hidden;
}

.formContainer {
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

height; 100vh;は高さを合わせる。

widht: 100%は横いっぱい使う。

align-items: で縦をセンターにし、

justify-content: centerで横をセンターにしまう。

そしたらこのようなログインフォーム真ん中によった画面になります。

 

次に真っ白なフォームを作成します。

.formContainer form {
  background-color: white;
  width: 70%;  
}

 

 background-color: whiteはバックグラウンドを白にしまう。

widht: 70%の意味は今のブラウザの70%分の横幅を取るという意味です。

なのでブラウザを大きくした場合はその大きくした画面の70%分の画面を取ります。

ですが、大きすぎてもいけない場合もあるので、

上限を設定します。

.formContainer form {
  background-color: white;
  width: 70%;  
  max-width: 450px;
}

max-widht: 450pxと設定することによって、

widthで70%表示したとしても、上限として450ピクセル(px)までしか表示できないように出来ます。

 

 そしたらログインフォームのおしゃれにしたいので、

paddingとborder-radiusを追加します。

.formContainer form {
  background-color: #f8ecec;
  width: 70%;  
  max-width: 450px;
  padding: 30px;
  border-radius: 10px;
  border: 1px solid #dfdfdf;
}

 padding: 30pxで内側の枠を広げます。

 border-radius: 10pxで角に丸みを出します。

border: 1px solid #dfdfdf;でボーダーの枠の線の色を変更します。

 

 box-shadowを追加しますが、今回は便利なサイトがあるので、こちらを使います。

 

 

hiroyuki-n.github.io

 

こちらでお好みのbox-shadowを作成して、影を作ります。

.formContainer form {
  background-color: #f8ecec;
  width: 70%;  
  max-width: 450px;
  padding: 30px;
  border-radius: 10px;
  border: 1px solid #dfdfdf;
  box-shadow: 34px 35px 61px -31px #777777;
  border-radius: 13px;
}


このような画面になります。

今の画面だと左に側によってしまっているので、真ん中の縦に綺麗に並ぶように整形します。
こちらはflexの知識が必要なので改めてやっていきます。
display: flexは全て横並びになるという意味です。
ですので、
flex-direction: column;で縦並びにします。
collumnというのは縦という意味です。
そしたら
align-items: center;が充てることができ、
justify-content: space-evenly;

.uiform {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  height: 400px;
}

追加で ログインフォームを中央に寄せたいので、

h1 {
  text-align: center;
}

 とCSSを当てます。

 

 次にユーザー名とinputの枠が横並びになっているので変更します。

こちらも先ほどと同じようにdisplay: flex;を使います。

.formField {
  display: flex;
  flex-direction: column;
}

そしたら縦並びになります。

そしたら、width: 100%を追加してください。

これは親要素に対して100%を取るので、ユーザー名に対して、100%取るようになります。

.formField {
  display: flex;
  flex-direction: column;
  width: 100%;
}

 

formFieldのinputタグを変更します。

.formField input {
  border: 1px solid grey;
  padding: 20px;  
  border-radius: 4px;
}

 border:1px solid grey;で枠の色をgreyに変更します。

padding: 20px;で枠を広げます。

border-radius: 4px;で枠を丸くします。

次にinputタグをクリックすると、枠が黒くなってしまうので、無効にします。

.formField input:focus {
  outline: none;
}

 

次にlabelを変更します。

.formField label {
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 3px;
}

 labelの文字のサイズが変更されました。

次にログインボタンが簡素な形になっていますので変更します。

button {
  background-color: #1b66a7;
  width: 100%;
  margin-top: 10px;
  border: none;
  border-radius: 5px;
  padding: 10px 30px;
  color: white;
  font-size: 15px;
  cursor: pointer;
}

 backgroun-colorで色指定

widht:100%で使う範囲設定

margin-top:10pxでマージンを取ります。

border:none;

padding:で縦横を広げます。

color: white;で文字の色を白

font-size: 15pxで文字の大きさ変更

cursor: pointerでカーソルが当たった時、ポインターになるようにします。

いい感じのログインボタンになりました。

最後にbuttonにホバーした時の挙動を加えます。

button {
  background-color: #1b66a7;
  width: 100%;
  margin-top: 10px;
  border: none;
  border-radius: 5px;
  padding: 10px 30px;
  color: white;
  font-size: 15px;
  cursor: pointer;
  transition: all 0.2s;
}

button:hover {
  background-color: #124877;
}

 これでCSSの設定はある程度は完成です。追加で必要なCSSもありますが、その都度追加します。

 

3.入力フォームのバリデーションチェック

例えば、ユーザー名が長すぎる場合、メールアドレスに@が含まれてない場合、パスワードが短すぎる場合にエラーを出したりします。

これをreact/javascriptで実装していきます。

方法としてはデータベースなどに格納するのですが、今回は状態変数をreactのhooksのuseStateで格納していきます。

src/App.jsに以下を追加します。

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

useStateフックの利用で関数コンポーネント内で状態管理を可能とするフックを設定します。useState(initialValues)ではinitialValuesのこの状態を初期値として設定し、

{ username: "", mailAddress: "", password: ""}というオブジェクトとして設定します。

状態宣言においては[formValues, setValues]で分割代入を使っています。

formValuesでは現在のフォームの状態を保持し、setFormValuesではその状態の更新をする為の関数になっています。

なので、initialValuesは'username','mailAddress','password'の各フィールドが空の文字列で初期化されています。

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

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

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormValues({ ...formValues, [name]: value });
  };
  return (
    <div className="formContainer">
      <form>
        <h1>ログインフォーム</h1>
        {/* <hr /> #横線を引くタグ# */}
        <hr />
        <div className="uiform">
          <div className="formField">
            <label>ユーザー名</label>
            <input
              type="text"
              placeholder="ユーザー名"
              name="username"
              onChange={(e) => handleChange(e)}
            />
          </div>
          <div className="formField">
            <label>メールアドレス</label>
            <input
              type="email"
              placeholder="メールアドレス"
              name="mailAddress"
              onChange={(e) => handleChange(e)}
            />
          </div>
          <div className="formField">
            <label>パスワード</label>
            <input
              type="password"
              placeholder="パスワード"
              name="password"
              onChange={(e) => handleChange(e)}
            />
          </div>
        </div>
        <button className="submitButton">ログイン</button>
      </form>
    </div>
  );
}

export default App;

 

 例えば、nameの変数ですが、

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

のname="username"のvalueに"tarou"と入力されれば、

const initialValues = { username: '', mailAddress: '', password: '' };

のusernameに格納されます。

これでinputを入力することでusernameやmailAddressを格納することができました。

最後に送信ボタンを押した時にログインを送信するように設定していきます。

今回はAPIを叩くような事はしませんが、バリエーションチェックのみを行っていきます。

 

 

 

 

 

 

ブラウザからURLを開くまでの挙動

ブラウザでURLを開くと何が起きるか。

DNSを通じて、クライアント(ブラウザ)はURLのホスト名を宛先サーバーのIPアドレスに解決する。そして3ウェイハンドシェイクによりTCP接続を確立する。TCP接続の上に、TLSハンドシェイクによってTSL接続を確立し、暗号化されたデータのみがネットワーク上で送信されるようにします。クライアントはHTTPプロトコルを使用して、ヘッダーとリクエスペイロードを含むリクエストを送信先のサーバーに送信します。サーバーは、ステータスコード、ヘッダー、レスポンスペイロードで応答します。

 

1.DNSルックアップ

ブラウザはURLのドメイン名(例えば、www.example.com)をIPアドレスに変換する為にDomain Name System(DNS)が使用されます。

ブラウザはDNSサーバーに問い合わせて、該当するIPアドレスを取得しまう。このプロセスではキャッシングがよく利用される為、既に知られているドメインの場合はこのステップはスキップされることがあります。

2.TCP接続

IPアドレスが分かったら、ブラウザはそのサーバーとの間に信頼できる接続を確立する必要があります。これを3ウェイハンドシェイクを通じて行われます。クライアントはSYN(同期)パケットをサーバーに送信し、サーバーはSYN-ACK(同期確認)パケットで応答し、最後にクライアントはACK(確認)パケットを送信して接続が確立されます。

3.TLSハンドシェイク

安全な通信を確保するために、殆どのウェブサイトではHTTPSを使用します。

これはTLS(Transport Layer Security)プロトコルを使った暗号化が含まれます。

TLSハンドシェイクは、クライアントとサーバー間で暗号化キーを安全に交換するプロセスです。これにより、送受信されるデータの盗聴や改ざんから保護されます。

4.HTTPリクエス

TSL接続が確立されたら、ブラウザはHTTPリクエストを送信します。このリクエストには求めているリソース情報、ブラウザの種類、受け入れている応答の形式など、多くのヘッダーが含まれています。

5.サーバー応答

サーバーはリクエストを受け取り、必要なリソース(HTMLファイル、画像、スタイルシートなど)を探します。見つかったリソースをHTTPレスポンスとしてブラウザに送り返し、ステータスコード(例:200 OK)、レスポンスヘッダー、そしてリクエストされたデータ(通常はHTML文章)が含まれます。

6.コンテンツの表示

ブラウザは受け取ったHTMLを解析し、ページに必要な追加的なリソース(CSSファイス、JavaScriptファイル、画像など)のリクエストを行います。

全てのリソースがロードされると、ブラウザはそれらを組み合わせてページをレンダリング(レンダリングとはHTML,CSS,Javascriptを人間がわかりやすいように生成される事)、ユーザーに表示します。

 

結論.

この一連のプロセスが行われる為、ユーザーはウェブページを見ることができます。

 

ただ近年では

A - Yay! (Atcoder)

問題概要

A - Yay!  / 
実行時間制限: 2 sec / メモリ制限: 1024 MB

問題文

問題文

英小文字からなる文字列  が与えられます。ここで  の長さは 3 以上 100 以下です。

 はある 1 文字を除いて全て同じ文字で構成されています。

他のどの文字とも異なる文字は前から何文字目でしょうか。

制約

  •  は 2 種類の英小文字からなる長さ 3 以上 100 以下の文字列
  •  はある 1 文字を除いて全て同じ文字

実装例

function main(input) {
    const chars = input.trim().split("");
    let charCount = {};

    // 各文字の出現回数をカウント
    for (const char of chars) {
        if (charCount[char]) {
            charCount[char]++;
        } else {
            charCount[char] = 1;
        }
    }

    // 唯一異なる文字を探し、その位置を出力
    for (let i = 0; i < chars.length; i++) {
        if (charCount[chars[i]] === 1) {
            console.log(i + 1); // 1-indexed にするために 1 を加える
            return;
        }
    }
}

// 標準入力からの読み込みを想定したコード
require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
}).on('line', (line) => {
    main(line);
    process.exit();
});

 

Paganation

問題概要

Mikeはウェブサイトの開発を担当しており、ページネーションの実装を任されました。
URLの配列urls、1ページあたりのURL数pageSize、表示する特定のページ番号pageが与えられたとき、
指定されたページに表示するURLを返す関数websitePaginationを作成してください。
例えば、url1からurl9までのURLリストがあり、1ページに表示するURLの数が3、目標とするページが2ページ目である場合、
この関数はurl4、url5、url6を含む配列を返すべきです。これらのURLは2ページ目に表示されるべきものです。

 

出入力例


Example 1:

Input: urls = ["url1","url2","url3","url4","url5","url6"], pageSize = 4, page = 1
Output: [url1,url2,url3,url4]

Example 2:

Input: urls = ["url1","url2","url3","url4","url5","url6","url7","url8","url9"], pageSize = 3, page = 2
Output: [url4,url5,url6]

Example 3:


Input: urls = ["url1","url2","url3","url4","url5","url6","url7","url8","url9"], pageSize = 4, page = 3 
Output: [url9]

 

実装(TypeScript)

function websitePagination(urls: string, pageSize: number, page: number): string {
    const startIndex: number = (page - 1) * pageSize;
    const endIndex: number = startIndex + pageSize;
    return urls.slice(startIndex, endIndex);
}

解説

1:開始インデックスの計算

まずそのページに最初に表示されるURLの配列内位置を特定する。

(page - 1) * pageSizeで計算される。

例えば、pageSize= 4, page = 3の場合は

(3 - 1) * 4となりstartIndex = 8になる。

そしたら配列内の9番目「url9」が開始インデックスになる

 

2:終了インデックスの計算

次に終了インデックスを特定する。

これはstartIndex + pageSize;で計算できる。

またpageSize = 4, page = 3で

8+4=12で[8:12]で5個抽出されると思うが,sliceメソッドは終了インデックス自体の要素は含まれないため問題ない。

 

3:URL抽出

最後に配列の`slice`メソッドを使用し、特定する。

コーディングTwo Sum

問題概要

1. Two Sum
整数の配列numsと整数targetが与えられたとき、それらの和がtargetになるような2つの数値のインデックスを返す関数を作成する。
各入力には正確に1つの解が存在すると仮定し、同じ要素を2回使用することはできない。

答えはどのような順序で返しても良い。

 

入力例 

Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
Example 2:

Input: nums = [3,2,4], target = 6
Output: [1,2]
Example 3:

Input: nums = [3,3], target = 6
Output: [0,1]

制約

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
Only one valid answer exists.

実装例

for文で回す事も出来るがワンパス・ハッシュ・テーブルアルゴリズムが使える。

具体的には反復してハッシュテーブルに要素を挿入している間に、現在の歩数が既にハッシュテーブルに存在するかをチェックしてもし存在すれば、インデックスに返す事が出来る。

const twoSum = function(nums, target) {
    const comp = {};
    for(let i=0; i<nums.length; i++){
        if(comp[nums[i] ]>=0){
            return [ comp[nums[i] ] , i]
        }
        comp[target-nums[i]] = i
    }
};

ブーリアン型

データとデータ型ではコンピュータでは0と1を使用する事を述べた。

そこで一つの形式であるブーリアン演算(boolean data type)のデータ型について説明する。ブーリアン型はTrueとFalseのリテラルで表現される。このブーリアン型は条件分岐(if文)などでの判断に用いられる。条件が成立する(true)成立しない(false)といった場合にそれぞれ異なる処理を行う事が出来る。

// 数値を出力  
console.log(true);      // trueを出力
console.log(false);     // falseを出力

// typeofを使って、データ型を調べる
console.log(typeof true);   // booleanを出力
console.log(typeof false);  // booleanを出力

この結果、

ユーザーが(有料ユーザー/無料ユーザー)

ユーザーがアンケートに(回答した/未回答)

文字列の長さが140文字以上(より大きい/以下)

 

などが処理の結果として扱われる。

データとデータ型

データ

データとは、プログラムが扱う情報。

プログラムが実行されると、何かしらのデータをもとに実行される。

例えば、ビジネスのアプリケーションの場合、顧客情報や売上がデータとして扱われる。このようなデータが数値、文字列、真偽値などの形式で表現される。

 

では具体的にコンピュータにおけるデータとは何を指すのか?

 

それはコンピュータの中で処理、保存されるデータは基本的に「0」と「1」の二進数の組み合わせによって表示される。これは電気的な信号のオンオフとして情報が処理される為。例えば、画像や文字列も二進数によって表現されており、データ転送や保存などもそれによって効率的に行えるようになっている。

console.log("Hello World!");

この場合Helloという文字列が0と1の二進数に変換されデータ転送される。

2進数をコンピュータで使う理由の一つは、ハードウェアを簡単に設計できる点にある。

基本的に、オンオフの二つの状態を持つスイッチ、すなわちトランジスタが必要。

このトランジスタの小型化が技術的な課題であったが、電気工学者、物理学者が解決していき、現代のトランジスタは砂粒の200,000倍も小さい5nmサイズまでに小型化が成功している。このトランジスタを組み合わせることによって、0と1の組み合わせでデータを表現する事ができる。

また、トランジスタには論理ゲートの作成にも利用される。論理ゲートとは特定の条件下で特定の動作を行う。例えば、AND(論理積)、OR(論理和)、NOT(否定)によって加算、減算、除算、乗算などの演算を行う。

だがこれらはハードウェアにおける詳細になるため割愛する。

要点として理解するべきは、コンピュータのデータが0と1に、ビットとして保存される事。