Reactについて学んでみた

React について何も知らない状態で、

https://ja.react.dev/learn/tutorial-tic-tac-toe#lifting-state-up

のチュートリアルをやりつつ、諸々疑問点を調べて概要を把握してまとめたもの。
今後実務で使う上での礎として。

# React とは
動的な Web サイトを作成するツールである。

各 Web ページを構成する「コンポーネント」を「コンポーネント関数」であらかじめ定義しておき、あるコンポーネント関数が別のコンポーネント関数を呼び出す入れ子のような形にして全体を実装していく。

クリックされたときに、コンポーネントに変化をつけたいときには「useState」という「フック」を利用する。

「プロジェクト構成」、「CSSの適用」、「ルーティング」については React 自身が推奨・提供するものはない。

# コンポーネント と コンポーネント関数
**コンポーネント**
ボタンやページ全体といった Web ページ上の UI の部品のことである。

**コンポーネント関数**
コンポーネント関数は、コンポーネントの情報を JSX で返す JavaScript の関数のことである。

コンポーネント関数には以下のルールがある。
- 関数名は大文字始まり。
- コンポーネントは、トップレベルで複数の JSX タグを返すことはできない。
    - 対策として、`<div></div>` で囲んで返したりする。

また、1モジュール(1ファイル)内のメインのコンポーネントには `export default` キーワードをつけて明示化する(のが慣習っぽい)。
コンポーネント関数には、別のコンポーネント関数をタグ`<【タグ名】 />`として埋め込むことができる。

```sample.jsx
// MyApp メインコンポーネント
export default function MyApp() {
  return (
    <div>
      <h1>サンプル</h1>
      <MyButton />
    </div>
  );
}

// MyButton サブコンポーネントのボタン 
function MyButton() {
  return (
    <button>ボタン</button>
  );
}
```

## JSX
```sample.js
<img className="avatar" src="https://i.imgur.com/yXOvdOSs.jpg"/>
```
という HTML と似たようなもの。
HTML より構文が厳格で、タグを閉じる必要がある。
- ✗: `<br>`
- ◯: `<br />`

JSX 構文でのコメントは、`/* */`または `//` が使える。
JSX タグの属性は、`<属性名>=<値>`でセットする。HTML で使える属性は、JSX では名前が異なるものがちらほらある。

例. 
HTML|JSX
---|---
class|className
onclick|onClick

### JSX における JS コード評価値の展開
`{<JSコード>}`で展開できる
ただし、 `onclick` などの操作系の属性値にセットする関数は、`()` なしで渡す。**「操作を受けて React が実行するから」**とのこと。

所感: 
公式のサンプルを見ていると、コンポーネントの関数内の構成は、
- 最後に JSX でそのコンポーネントの実態を返す。
- JSX 内で使いたい操作イベントに対してトリガーするJSの関数定義や、JSの変数値の計算は先に済ませておく
という形にするのが通例っぽい？

```sample.jsx
export default function MainCopmponent() {
  const user = {
    imageUrl: "https://i.imgur.com/yXOvdOSs.jpg",
  };

  function handleClick() {
    alert('You clicked me!');
  }
  
  return (
    <img
      className="avatar"
      src={user.imageUrl}
      onClick={handleClick}
    />
  );
}
```

### props
JSX タグの属性のこと。
`<button>`等の組み込みコンポーネント( HTML でもともとタグとして用意されているやつ ) は、使用可能な props 名が定められており、変更不可である。
対して、自身で定義するコンポーネントは、props 名を自由に決定できる。
独自コンポーネントの props 名は、コンポーネント関数の仮引数で定義できる。このとき、仮引数は `{}` で囲む必要がある。

**参考:** 
- [コンポーネントに props を渡す](https://ja.react.dev/learn/passing-props-to-a-component)

```sample.jsx
// React のフック useState を使用
import { useState } from 'React'

// 独自コンポーネント MyApp
export default function MyApp() {
  const [count, setcount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  )
}

// 独自コンポーネント MyButton
// count, onClick は MyButton コンポーネントの props (属性)
function MyButton({ count, onClick }) {
  return (
    <button onClick={onClick}>
      Clicked {count} times
    </button>
  );
}
```

#### ハンドラ関数とハンドラ関数を受け取る props の命名
React では、以下の慣習になっている
- イベントを処理するハンドラ関数を受け取る `props` 名: `onXxx`
- イベントを処理するハンドラ関数自体の名前: `handleXxx`

そのため、複数のコンポーネントの入れ子担っている場合、`onXxx` の `props` に初っ端にわたすときには `handleXxx` 以降入れ子のコンポーネント内では、すべて `onXxx` として受け渡されていくことになる。

**所感:** 
よく考えれば妥当なのだが、個人的にはここがややこしくて混乱してしまった。
- 特定のコンポーネントに、`handleXxx` 渡すところを見かけたらそれはハンドラ関数が最初に渡される場面であり、具体的な処理内容を確認できる場面
- `onXxx` をコード内で見かけたら、それはハンドラ関数が幾度か経由して間接的に渡されてくる場面であり、どんな処理が渡されるのかは呼び出し元次第

という意識でいれば、そんなに混乱しない。
(これも個人的な感覚だが)

**参考:**
- [stete のリフトアップ - 補足](https://ja.react.dev/learn/tutorial-tic-tac-toe#lifting-state-up)

# プロジェクト構成
デファクトスタンダードは存在しない模様。

[古い公式ドキュメント](https://ja.legacy.reactjs.org/docs/faq-structure.html)によると、
「Reactとしては、プロジェクト構成の推奨や規定はしていない。ただ、Reactエコシステムでは、以下のような形がよく見受けられるよ」と述べられている。
- 機能 or ルート別にグループ化
- ファイルの内容のタイプ別にグループ化



# CSSの適用
デファクトスタンダードな方式は 存在しない模様。よくある方式としては、以下のようなものらしい。

1. CSS ファイルを複数作り、CSS Module というライブラリを使ってインポートする
2. CSS ファイルを作らず、コンポーネントの JS ファイル上に直接定義して適用する

# ルーティング
React 自身には用意されていない。
サードパーティのライブラリを使ったりして実装する。
デファクトスタンダード は React Router というものらしい。

# フック
再利用可能な UI ロジックである `use` で始まる名前の便利関数(`useState`)
React に標準で用意されているフックは「組み込みのフック」と呼ばれる(組み込みのフック = React の本体たる機能であるっぽい)

組み込みのフックは、以下のように分類されている。
- state
- context
- ref
- effect
- performance

参考: 
[組み込みの React フック](https://ja.react.dev/reference/react/hooks)

## state - useState
コンポーネントに state 変数を追加する組み込みのフック。

クリック等のイベントがトリガーされたときに、コンポーネントに変化をつけたいときに利用する。

イベントのトリガーにより、変化をさせたい対象のコンポーネント関数について、
- state を宣言
- JSX が state に基づいて生成される & その state がユーザーの特定の操作により変化するようにする

という形で実装すると、

1. ユーザーが特定の操作をした際に state の変更が React へ伝わる
2. React は、変更後の state の値に基づく表示内容を計算する
3. 前回と表示内容に変化があれば React が再描画する

というような動きをしてくれる

**サンプルコード:**
```sample.jsx
import { useState } from 'react'

// MainComponent
export default function MainComponent() {
    return (
        <div>
            <SubComponent className="abc"/>
        </div>
    );
}

// SubComponent
function SubComponent({ className }) {
    const [testState, setTestState] = useState(100)

    handleClick() {
        setTestState(testState + 1);
    }
    
    return (
        <button className={className} onClick={handleClick}>
            テキスト{testState}
        </botton>
    );
}
```

上記のサンプルコードでは、最初に「テキスト0」というボタンが表示されていて、これをクリックすると「テキスト1」にボタンが変化する。

このときの React 内部処理としては、以下のような流れで進むイメージ。
1. ボタンをクリック → `handleClick` 発火
2. `handleClick` により `testState` が 0 → 1 に
3. 2. を React が検知して `testState` が 1 の場合のと `0` の場合の表示内容を計算
4. 3. に差分があるため`testState` が 1 の状態でボタンを再描画

参考: 
[リファレンス](https://ja.react.dev/learn/state-a-components-memory#meet-your-first-hook)

### `useState(<初期値>)`
`useState(<初期値>)`の返り値は、`[<現在のstate>, <set関数>]` という配列である。

返り値は、慣習として `const` + 分割代入`[<state名>, set<state名>]` の形で受けとる。

```sample.js
// 初期値: 0 の state を宣言
const [index, setIndex] = useState(0);
```

### set関数
次回の「レンダー」で使う `state` 変数の値をセットする関数。
`set` 関数を呼び出した後に `state` 変数を読み込んでも、その値は現在の `state` の値のままである。

同一コンポーネントで同名の `set` 関数を何回呼び出しても、次回のレンダーは最後に実行した `set` 関数 による `state` の値によって行われる。

また、全コンポーネント内のイベントハンドラによる全 `state` 変数の更新がすべて完了した状態で、レンダーがトリガされるらしい。


### レンダー
以下のように理解している。

- レンダーとは、React がコンポーネントを呼び出すことである。
- `useState` オブジェクトの初期化で生成される `set` 
 関数を呼び出すと、その `useState` オブジェクトが存在していたコンポーネントについて、レンダーがトリガされる。
- React は再レンダーするたびに前回のレンダーとの差分を確認し、その差分を再描画する。
- `set` 関数による `state` 値の変更処理に、state変数自体が使われている場合、使われている `state`の値は、前回レンダー時の `state`値である。
    - 初回レンダー時は、初期値が使われる。
- `state`値の変更後の値は、次回レンダー時に反映される。
    - 複数回 `state` 値を変更する処理を記述したとて、最後に事項される変更処理による値が適用される。

以下のサンプルコードでは、初期描画時には0のボタンが表示され、クリックすると1のボタンが表示されるという形になる。

```sample.jsx
import { useState } from 'react'

function MyButton () {
  const [value, setValue] = useState(0)

  function handleClick() {
    // このコンポーネント内で何回呼び出されようとも、valueは前回レンダー時の値が使われる
    // ただし、初回レンダー時はvalueは初期値が使われる
    setValue(value + 1); 
    setValue(value + 1); 
    setValue(value + 1); 
  }
  
  return (
    <div onClick=handleClick>
      {value}
    </div>
  );

}
```

もちろんではあるが、useStateを使わず

```sample.jsx

function MyButton () {
  value = 0;

  function handleClick() {
    value = value + 1;
  }
  
  return (
    <div onClick=handleClick>
      {value}
    </div>
  );

}
```

としても、set 関数をこのコンポーネントに対して呼び出してないので state は変更されず、したがってレンダーもトリガーされないため、ボタンをクリックしても0のまま変わらない。

**参考:**
[state はスナップショットである](https://ja.react.dev/learn/state-as-a-snapshot)

### stateの共有

> 複数の子コンポーネントからデータを収集したい、あるいは 2 つの子コンポーネント同士で通信したい、と思ったら、代わりに親コンポーネントに共有の state を宣言するようにしてください。親コンポーネントはその state を子コンポーネントに prop 経由で渡すことができます。これにより、子同士および親子間で、コンポーネントが同期されるようになります。

とのこと
(引用元: [チュートリアル : 三目並べ - state のリフトアップ](https://ja.react.dev/learn/tutorial-tic-tac-toe#lifting-state-up))


# 便利なツール
- [React Developer Tools](https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ja&pli=1)
各ブラウザの拡張機能として利用できるもので、React コンポーネントの props や state を確認できるようになる。chromeだと「ファイルの URL へのアクセスを許可する」をONにしておくと、ローカルのものも対象にできる。
- [HTML から JXS に変換するオンラインコンバータ](https://transform.tools/html-to-jsx)