React始めました

Reactで何か作ろうと思ってずっと先延ばしになっていたんですが、
ようやく勉強を始めることができました！

で、学んだことをゆるーく備忘録として残していこうと思います。

お手柔らかにお願いします！

## ファイル準備
ディレクトリ構成はこんな感じ

```
app
 └─ public
     └─ scripts                     
```

```html:app/public/index.html
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>React Lesson</title>
</head>

<body>
  <div id="app"></div>
  <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="./scripts/app.js"></script>
</body>

</html>
```

```react:app/public/scripts/app.js
// 一旦中身は空
```

## Hello React
ファイルの準備ができたので`Hello React`を表示できるようにしていきます。
どうやらReactはHTMLのタグをjsファイルに記述できるらしいのでとりあえず書いてみます。

```react:app/public/scripts/app.js
const template = <h1>Hello React</h1>;

const appRoot = document.getElementById("app");

ReactDOM.render(template, appRoot);
```

`ReactDOM.render`の第一引数に<font color="Red">描画するHTML</font>、第二引数に<font color="Red">描画する場所</font>を渡せば`template`に代入したHTMLが描画されるっぽいです。

さあ、いざHello Reactを表示！！！

![スクリーンショット 2022-06-10 1.40.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843917/61800563-1940-56df-2c84-0552a14dce96.png)
ん？
まあ、そうですよね。
`<`は比較演算子ですから。。。
公式ドキュメントによると**JSXと呼ばれるJavaScriptの構文を拡張したもの**らしいです。
JSXはBabelでコンパイルする必要があるのでパッケージをインストールします。

```
npm i -D @babel/cli @babel/core @babel/preset-env @babel/preset-react
```

コンパイルしたapp.jsは`app/public/scripts/app.js`に配置したいので、現在のapp.jsは`app/src`に移動させます。
移動できたらコンパイルのコマンドを叩いて表示されるか確認します。

```
npx babel src/app.js --out-file=public/scripts/app.js --presets=@babel/preset-env,@babel/preset-react --watch"
```

![スクリーンショット 2022-06-10 1.53.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843917/f7c10181-7945-6083-6127-fa8000a7e106.png)
無事表示されました^^

今度はサブタイトルとして「初めてのReact」も表示しようと思います。

```react:app/src/app.js
const template = <h1>Hello React</h1><h2>初めてのReact</h2>;

const appRoot = document.getElementById("app");

ReactDOM.render(template, appRoot);
```

コンパイルできませんでした。。。

![スクリーンショット 2022-06-10 1.57.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843917/46cc9927-14b6-9880-da21-01e17614e3bb.png)

JSXで兄弟要素を描画するときは、どうやら親要素が必要みたいです。
ただ、そのためだけにdivタグを使うのは美しくないので**fragment**というものが用意されているみたいです。(Vueでいうところのtemplateタグと同じ感じだと思います)
早速、fragmentを使ってサブタイトルを表示しようと思います。

```react:app/src/app.js
const template = (
  <>
    <h1>Hello React</h1>
    <h2>初めてのReact</h2>
  </>
);

const appRoot = document.getElementById("app");

ReactDOM.render(template, appRoot);
```

![スクリーンショット 2022-06-10 2.02.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843917/28662e3b-0a2f-f066-e027-f3289c716790.png)
今度はちゃんと表示されました^^

## コンパイルされたファイルを覗く
`app/src/app.js`のコンパイル先は`app/public/scripts/app.js`なので早速ファイルを開いてみる。

```javascript:app/public/scripts/app.js
"use strict";

var template = /*#__PURE__*/ React.createElement(
  React.Fragment,
  null,
  /*#__PURE__*/ React.createElement("h1", null, "Hello React"),
  /*#__PURE__*/ React.createElement("h2", null, "\u521D\u3081\u3066\u306EReact")
);
var appRoot = document.getElementById("app");
ReactDOM.render(template, appRoot);
```
`React.createElement`は第一引数に<font color="red">タグ</font>、第二引数に<font color="red">属性</font>、第三引数に<font color="red">タグの内側に来る内容</font>を渡すみたいです。
また、`createElement`の返り値は**React要素**と呼ばれるものになるらしいです。
React要素はHTMLの要素をJavaScriptのオブジェクトに変換したようなもののイメージで大丈夫っぽいです。

`React.Fragment`は描画したいHTMLが兄弟要素だったときに、仮の親要素みたいな存在になってくれるやつですね。
これ→`<></>`

`ReactDOM.render`の第一引数に<font color="red">React要素</font>、第二引数に<font color="red">描画する場所(DOM)</font>を渡せば描画してくれるみたい。

んー、Babelさん、すごいっす。。。

### JSX内でJSの構文を使う
これまで描画した内容は静的なものでしたが、動的にするにはJSX内で`{ }`を使えば実現できます。

```react:app/src/app.js
onst user = {
  name: "なべし",
  age: 26
};

const template = (
  <>
    <h1>名前: {user.name}</h1>
    <h2>年齢: {user.age}</h2>
  </>
);

const appRoot = document.getElementById("app");

ReactDOM.render(template, appRoot);
```
これで動的になりましたね。
マスタッシュ構文みたいですね。

とりあえず今回はこのくらいにしておきます。

では、また！

## 補足
React 18は`ReatDOM.render`が非推奨で、
代わりに、`ReactDOM.hydrate`を使用するみたいです。

`ReactDOM.hydrate`はサーバーサイドで生成されたDOMとクライアントサイドで生成された仮想DOMを比較して、
一致していればスキップ、一致していなければ再レンダリングが行われるそうです。