Reactをjavaで理解する

### 概要
React未経験のため、公式サイトを見ながら少しだけ概要を把握した。
Javaや従来のJavaScriptと比較しながら理解を深めたので、その記録を残す。
また、よく使われるReact向けのライブラリについても記載する。

### Reactについて

#### HTMLファイルは不要

Reactでは、UIのレンダリングをJavaScriptファイルのみで完結できる。
画面作成初心者は「HTMLがUIで、JavaScriptがロジック」と教わると思うが、Reactの場合はJavaScriptだけでUIもロジックも書ける

例えば、以下コードを例にして話すと、
Reactがブラウザ上でreturn()内の描画を行うため、個別にHTMLファイルを用意する必要がない。
※ 厳密にいうと、Reactアプリの描画先となるルート要素を設定する「ベースのHTMLファイル（index.htmlなど）」は必須だが、これは実質的に設定ファイルのような役割を果たしている。
```react
export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
    </div>
  );
}
```


#### 仮想DOM

JavaScript上のGitのような仕組み。
出力されたDOM（HTML）のコピーを保持し、DOMの更新が必要なときは、更新前後の差分を検出して、差のある部分だけを効率よく書き換えてくれる。

更に仮想DOMの大きな特徴は状態を保持できること。
例えば、下記のコードのようにコンポーネント内で状態を管理する変数`const [isOn, setIsOn] = useState(false);`を定義すると、コンポーネントを複数回呼び出して描画しても、それぞれ独立したUIとして管理される。
つまりJavaでいうと、`<App />`を呼び出すごとにAppクラスのインスタンスが生成されており、`useState`で生成した変数がフィールド変数のような役割を持つイメージ。
そのため、1つ目の<App />で表示されたボタンを押して状態が変わっても、2つ目の<App />には影響がない。

```react
export default function MyApp() {
  return (
    <div>
      <App />
      <App />
    </div>
  );
}

function App() {
  const [isOn, setIsOn] = useState(false); // 状態と、更新用の関数を定義

  return (
    <div>
      <p>{isOn ? 'ON' : 'OFF'}</p>  {/* 状態に応じた表示 */}
      <button onClick={() => setIsOn(!isOn)}>トグル</button> {/* 状態を反転 */}
    </div>
  );
}
```

#### コンポーネントとは

Reactのコンポーネントは、Javaでいうメソッドのようなもの。
UI（見た目）とロジック（動作）を合わせて定義できるため、再利用が簡単にできる。

ちなみに、ReactでHTMLのような記述ができるのは、JSXという拡張構文のおかげ。JSXはJavaScriptの中でHTMLに似たコードを書ける仕組み。

#### 状態（useState）

Reactの公式サイトなどでよく出てくる“状態”とは、`useState`を使って定義するstate変数のこと。これはJavaのフィールド変数に似ている。  
`useState`はReactが提供する機能の一つで、状態管理を簡単に扱うためのAPI。フック（Hook）という仕組みの一つ。  

実際のコードで言うと`useState`を使って変数を定義＆初期化すれば、そのコンポーネントが再レンダリングされても値を保持する変数を定義できる。つまりコンポーネント内のUIに`<button onclick="state変数の値を変更するメソッド" >`があるとして、ボタン押下すれば、コンポーネント内の処理が実行されてUIがサイレンダリングされるが、state変数については初期化されずにボタン押下前の値が引き継がれて使用される。

Javaでいうとクラス内クラスとインスタンス変数を纏めて定義しているイメージに近い。

```react
import { useState } from "react";

export default function Board() {
  const [xIsnext, setXIsNext] = useState(true);
  const [squares, setSquares] = useState(Array(9).fill(null));
  );
}

```

#### コンポーネントにおける再レンダリングの注意点

コンポーネントの再レンダリングは、そのコンポーネントが保持するstate変数のsetterが呼ばれて値が変わったとReactが検知した場合に、そのコンポーネントのみ再レンダリングされる。  
ただプリミティブ型と参照型の差分検知方法の違いには注意したい。  

  ⇒ プリミティブ型
setで値を変更すると、その値自体が比較され差分ありと判断される。  
例えば下記の`xIsNext`はプリミティブ型(boolean)なので、true→falseに変われば差分とみなされ再レンダリングされる。

  ⇒ 参照型
参照先（オブジェクトの仮メモリ上の場所）を比較している。  
下記コードの`squares`は配列オブジェクトのため、要素を変更しても参照先が変わらない限り差分なしと判断される。  
そのため、`const nextSquares = squares.slice();`で配列の内容のみコピーし、新しい配列として仮想メモリを新たに確保する。  
`setSquares(nextSquares);`を呼ぶことで`squares`の参照先が変わり、差分ありとみなされる。

```react
export default function Board() {
  const [xIsnext, setXIsNext] = useState(true);
  const [squares, setSquares] = useState(Array(9).fill(null));
  let status;

  function handleClick(i) {
    if (squares[i] || calculateWinner(squares)) {
      return;
    }
    const nextSquares = squares.slice();
    if(xIsnext){
      nextSquares[i] = "X";
    }else{
      nextSquares[i] = "O";
    }
    setXIsNext(!xIsnext);
    setSquares(nextSquares);
  }

  return (
    <>
      <div className="status">{status}</div>
      <div className="board-row">
        <Square value={squares[0]} onSquareClick={() => handleClick(0)}/>
      </div>
    </>
  );
}

```

  ⇒ ちなみに、プリミティブ型と参照型で比較の仕組みが異なる理由は、プリミティブ型は物理メモリ上に値そのものを保持しているのに対し、参照型はオブジェクトの構造や管理情報なども含んでいる。
そのため、参照型全体を比較すると非効率であり、誤った差分検出が起こる可能性がある。だから参照型は仮想メモリ上の参照先（アドレス）のみを比較する仕組みになってる。

#### key属性について

以下のコードは、配列`history`の要素を順に取り出して`<li>`要素としてレンダリングする処理である。このようなリストを描画する場合、各要素に`key属性`を付与することが推奨されている。  
```
const moves = history.map((squares, move) => {
  //...
  return (
    <li key={move}>
      <button onClick={() => jumpTo(move)}>{description}</button>
    </li>
  );
});
```
なぜなら、再レンダリング時にリストの一部が削除・追加・並び替えされた場合、Reactは要素の内容だけでは差分を正確に判別できないことがある。`key`を付与することで、Reactは「どの要素がどの位置にあるか」を明確に識別できるため、より正確かつ効率的な差分更新が可能となる。

  特に`<li>`の中にユーザーが入力するフォームなど状態を保持する要素がある場合、key がないと React は要素を使い回せず、新たに作り直してしまい、入力内容がリセットされるなどの問題が発生する。
key を適切に指定すれば、Reactは不要な部分を再描画せず、状態を保持したまま必要な差分だけを更新してくれる。

注意点：
key は そのリスト内で一意な値 を指定する必要がある。
index（上記こーでいうと`move`のこと。要素の「何番目」）を key に使うのは原則避ける（ただし順番が変わらない・固定ならOK）。
なぜ index の使用を避けるべきかというと、リストの先頭または途中の要素が削除・追加された場合、後続の index 値がずれてしまうため。
その結果、React が「前回DOM」と「今回DOM」とを比較した際に、本来同じ要素であるにもかかわらず異なるものと誤認識される。
すると、key が一致しないものは「新しい要素」と見なされ、React はそれらを再レンダリングしてしまうため、意図しない UI の更新や、フォーム内容のリセットなどが発生する可能性がある。

keyまとめ：
key は「これは前回と同じ要素だよ」とReactに伝える唯一の識別子。
だから index のように変化しやすい値を使うと、差分検出の精度が落ちる。

### Redux（レダックス）について

ReduxはReactの「状態管理」を楽にするためのライブラリ。
アプリ全体で共有される「状態（state）」を一元管理できる。
Javaでいうところのpublic static変数のようなイメージに近い。

ただし、Reactはフロントエンドのライブラリなので、「アプリ全体」とは基本的にブラウザ上の範囲を指すと考えたほうがしっくりくるかも。

なぜReduxを使うと便利なのかというと、主に以下の理由がある。

状態が変更された瞬間にリアルタイムで参照しているUIに反映してくれる。
参照元で変更を検知する仕組みを自分で用意する必要がなく、Reduxが自動的に管理してくれる。

変更履歴を記録してくれるためデバッグがしやすい。
いつどこで状態変更の要請があったのかを記録し、開発中に想定外の更新があってもツールで可視化・追跡可能。

### 総括
JavaとJavaScriptの両方を経験している人にとっては、基本的な部分を理解するだけ敷居が低いライブラリ