Reactの基礎学習(Stateについて)

# 概要
Reactを勉強し始めたので、学習用＆記録用にまとめる

# 学習に使用している本
https://wings.msn.to/index.php/-/A-03/978-4-8156-1948-0

# Reactとは
JavaScriptのライブラリの一つ。
学習コストが低くて習得しやすいとのこと

# 早速実践
### 1. Reactアプリを生成
```
$ cd {配置したいディレクトリ}
$ npx create-react-app test
```
### 2.index.htmlを編集する
* 元あるものから最低限の記述にした
```html:index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>てすと</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
```

### 3.index.jsを書き換える(srcディレクトリの直下)
* 元あるものから最低限の記述にした
* `root.render()`の中身が、 index.html の id=root の要素に入る
```react:index.js (最初に呼び出されるファイル)
import React from 'react';
import ReactDOM from 'react-dom/client';
import Test from './test/';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <>
        <Test />
    </>
);
```
### 4.コンポーネントの作成
・index.jsで呼ばれてる`<Test />`を作っている
```react:Test.js
import { useState } from 'react';

export default function Test() {
    // A.stateを初期設定
    const [form, setForm] = useState( // Stateの初期値を設定
        {
            name: "あきら",
            age: 18,
            country: "日本",
            isEdit: false
        }
    );

    // B.文字列変更時の処理
    const changeEvent = e => {
        setForm({
            ...form,
            [e.target.name]: e.target.value, // e.target でイベント発火した要素が取得できる
            isEdit: true
        });
    };

    // C.送信ボタン押下時の処理
    const sendEvent = () => {
        console.log(`コンソールログ 名前：${form.name} 出身：${form.country} 年齢：${form.age}`)
    };

    // D.画面表示
    return (
        <form>
            <div>
                <label htmlFor='name'>おなまえ：</label>
                <input id='name' name='name' type='text' onChange={changeEvent} value={form.name} />
            </div>
            <div>
                <label htmlFor='age'>ねんれい：</label>
                <input id='age' name='age' type='number' onChange={changeEvent} value={form.age} />
            </div>
            <div>
                <label htmlFor='country'>しゅっしん：</label>
                <input id='country' name='country' type='text' onChange={changeEvent} value={form.country} />
            </div>
            { form.isEdit &&
                <div>
                    <button type="button" onClick={sendEvent}>そうしん！</button>
                </div>
            }
            
            <p>
                {(form.country === '日本' || form.country === '東京') && 'ご近所の'}
                {(form.country !== '日本' && form.country !== '東京') && form.country + 'からはるばるやってきた'}
                {form.name}さん ( {form.age}歳 ) ！よろしく！
            </p>
        </form>
    )
}
```

### 4. 実行！
```
$ cd {配置したいディレクトリ}/test
$ npm start
```

### 5. 結果
▼ 初期表示
![スクリーンショット 2024-06-09 100726.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719849/2abb15f7-342b-5155-e10c-4aed2f4d62a7.png)
▼ 入力変更
![スクリーンショット 2024-06-09 100903.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719849/a7d6d0c1-31b4-a406-c99b-7f72100496c4.png)

### 6. 「4.コンポーネントの作成」について
#### まず.stateとは
* コンポーネント内の状態を表す変数
* 画面表示に子の変数を使うことで、変数の値が変更されたときに画面表示が更新される(値が使われている部分だけ)

#### A.stateを初期設定
* stateを使うときの定型文
* form という変数の初期値を設定している
* 以降はsetFormという関数によって、formの値を変更できるようにしている

#### B.文字列変更時の処理
* 画面で文字入力を変更したときに呼び出している関数(onChangeで呼び出している)
* A.で定義した「setForm」を使って値を更新している
* `[e.target.name]`のように変数を[]で囲うことで、e.target.nameの値をプロパティ名として使っている
    * つまり、e.target.name(イベント発火した要素のname属性)はA.で設定したプロパティ名(name, age, country, isEdit)と一致している必要がある
* `...form`はスプレッド構文で、オブジェクトのコピーを作って分解しているもの
    * 即ち、`...form`で現在の値をすべてもってきて、変更したい値(`[e.target.name]: e.target.value`と`isEdit: true`)だけさらに設定して上書きしている

#### C: 送信ボタン押下時の処理
* 送信ボタン押下時(onClick)に呼び出している関数
* コンソールログに値を出力しているのみで、最新状態の値がとれる

#### D: 画面表示
* 「おなまえ」「ねんれい」「しゅっしん」の入力のタイプはそれぞれ異なるが、構成はおなじ
* `<label>`は項目名表示
* `<input>`は入力欄
    * id：今回は一意になるように設定しているのみ
    * name：入力変更時に変更したい変数名を設定（おなまえであれば初期値「あきら」になっている`name`）
    * type：入力欄のタイプ。おなまえとしゅっしんはもじにゅうりょくで、ねんれいは数値になっている
    * onChange：入力変更時に呼び出す関数(B.)を設定
    * value：A.の変数をそれぞれ設定。こうすることで初期表示時に設定した初期値を出力できる
        * ここをなしにすれば、画面表示上は入力欄を空欄にできる
* `{ form.isEdit && ~~~ }`は、送信ボタンの表示
    * isEditは初期値はfalseなので`<div>~~</div>`が表示されないが、一度でも入力が変更されればB.によってtrueになるので表示される仕組みにしている
    *一番最後の`<p>～～</p>`は入力値でリアルタイムに変更されるテキスト表示で、仕組みはisEditの部分と同様