React公式チュートリアル挑戦課題を経て感想

本記事ではReact初心者が公式チュートリアルの挑戦課題をへて思った、Reactの感想を述べます。
ポエムです。
初心者のころの気持ちを忘れないために書きます。

React公式チュートリアルでは三目並べ（○✖️ゲーム）を実装することができ、
「タイムトラベルの実装」の解説まで超丁寧に記述してくれています。
なお、挑戦課題はヒントすらない笑
**公式チュートリアル**
https://ja.reactjs.org/tutorial/tutorial.html
## 要約
- React公式チュートリアルの三目並べにある**挑戦課題**が難しい
- React基礎を体系的に学べるめっちゃいい問題だった
- Reactムズおもろい

### できたもの
三目並べ（○✖️ゲーム）
![画面収録_2022-08-23_22_40_30_AdobeExpress (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650886/0cf0abe1-211d-70ad-3b89-6ef6cff6a1fb.gif)

完成コード　※挑戦課題のネタバレを含みます
https://codepen.io/Yamadamadamada/pen/poLpxmp

## Reactを始めた経緯
新しくReact案件に入ることになり、社内チームで毎朝開催している勉強会でReactを学習させてほしいとお願いしたのでした。。。
毎朝１時間Reactを勉強する時間をいただき、チュートリアル挑戦課題を終えるまでに1ヶ月かかったというオチ。
全て終わるまでに合計２０時間くらいかかりました。

## 思ったことツラツラ

### render ？ return ？公式さんタイポしてません？
してません。

Reactには**要素**という概念があり、 Reactアプリケーションの最小単位の構成ブロックです。
後掲しますが、要素は**コンポーネントとは違います**。
```jsx
// 1つのReact要素
const element = <h1>Hello, world</h1>;
```

`render()` に React要素を渡すと、画面にDOM（HTML形式）にして描画してくれます。

```jsx
// 要素を DOM として描画する
const root = ReactDOM.createRoot(
  document.getElementById('root')
);
const element = <h1>Hello, world</h1>;
root.render(element);
```

コンポーネントは画面に表示する**React要素を返す**クラスや関数を指します。
下のコードはどちらも同じ画面が表示されます。

```jsx
// 関数コンポーネント
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// クラスコンポーネント
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
```

で、結局renderはなにかというとクラスコンポーネント内で、生成したいDOMと要素を置く場所になります。
そしてreturnは実際に表示するDOMを返す場所です。（！？）

言葉にするとわかりにくいのでコードで書くと、
要素はrender内で定義することができますがrenderにいるだけでは画面に表示されず、`return`にある要素またはコンポーネントが実際に描画されるDOMになります。
（クラスコンポーネントの場合）
```jsx
// クラスコンポーネント
class Welcome extends React.Component {
  render() {
    const element = <span>renderの中で定義するよ〜<span>;
    return <h1>Hello, {element}</h1>;
  }
}
```

クラスコンポーネントの場合、とありますが、関数コンポーネントはrenderを使いません。私は業務でクラスコンポーネントを使っていないのでrenderを意識することはありません

**まとめ**
- 画面に表示するにはreturnの中に書けばいいんだな〜
- 関数コンポーネントしか使わない場合、renderのことは忘れて大丈夫！！！（暴論）


### なんで戻り値にHTMLタグ入ってるんだ...
それがReactだから。

Reactはマークアップとロジックを両方含む疎結合の「コンポーネント」単位でコードを記載します。

[単一責任の原則](https://ja.wikipedia.org/wiki/SOLID)に基づき単一のコンポーネントにJSXタグ、状態管理、イベントリスナをまとめて書くことで１つの部品が１つの役割を全うするように設計されています。


**まとめ**
- Reactはコンポーネントにマークアップもロジックも込み込みで一つの部品として独立している
- 単一責任の原則にもとづき１つのコンポーネントには１つの機能しかもたせない


### １マスを表示するのにコンポーネント分離しすぎだろ...
それがReactだから。（２回目）

チュートリアル内の三目並べでは９マス表示するのに１つのクラスコンポーネントと2つの関数コンポーネントに分離しています。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650886/2d1e86a5-6e91-169e-13c9-65c4aaa7fc48.png" />

それそれの役割を見ていきましょう

- Square
    - 関数コンポーネント
    - renderSquareから○か✖️を受け取り表示する
    - クリックされたとき、発火イベントを親のrenderSquareへ知らせる
- renderSquare
    - Board内にある関数コンポーネント
    - マスの順番をBoradから受け取り、○か✖️を判断しSquareへ渡す
    - Squareで起きたクリックイベントをBoardへ渡す
- Board
    - クラスコンポーネント
    - renderSquareへマスの順番、◯か✖️かの情報を渡す
    - renderSquareから受け取ったクリックイベントに対し、処理を行う

...はい！ややこしいですね！！！

- `Square`　１マスを表示
- `Board`　1マスを9個まとめる
- `renderSquare`　ただデータをバケツリレーしてるだけ


Reactは１コンポーネントに対し、１つの役割しか持たせません。上記の例だと、
`Square`コンポーネントは「１マスを表示する」ことしかしません。
クリックしても、イベントを親コンポーネントへ**知らせるのみ**で、イベント処理を**記述しません**。

また、`Board`コンポーネントは
「`Square`コンポーネントへデータを渡す」「イベント処理を行う」など、
**状態管理を行うのみ**で表示には関与しません。

そして、`renderSquare`コンポーネントはコンポーネントへデータを受け渡しする際にデータを整形して渡し、親と子それそれのコンポーネントが影響し合わないようにしてくれているコンポーネントです。
（コンポーネントのゲシュタルト崩壊）


**まとめ**
- 親子コンポーネントは親が状態管理を行い、子が描画を担当する
- データのバケツリレーしがち


### state?Vueのrefみたいなやつ？
違います。が、ReactにもuseRefなるものはあります。

Reactにはコンポーネント内でデータ管理ができる`state`オブジェクトが存在します。
`state`オブジェクトの１つである`useState`は定義した変数をフックし値を更新することができます。

ReactとVueのそれそれで簡単な数字カウンターを記述してみます。

Reactのカウンター
```jsx
import React, { useState } from "react";

function App() {
  // 『state変数』を宣言。初期値を設定。
  const [count, setCount] = useState(0);
  return (
    <button type="button" onClick={() => setCount(count + 1)}>
      count is {count}
    </button>
  );
}

export default App;
```

Vueのカウンター
```vue
<script setup>
import { ref } from "vue";
// 初期値を設定
const count = ref(0);
</script>

<template>
  <button type="button" @click="count++">
    count is {{ count }}
  </button>
</template>
```


Vueのrefでは`count`変数に対し、表示もイベント発火もイベント処理も全部まとめて行うことができます。
しかし、Reactの`count`変数は**表示しかできません。**

これは、`setCount`が更新の役割、`count`が表示の役割を別で持つことで、
異なるコンポーネント間でステートフルな振る舞いを共有することができる...らしいです。

[公式いわく(要するにフックとは)](https://ja.reactjs.org/docs/hooks-overview.html#but-what-is-a-hook)

**まとめ**
- 関数コンポーネントはstateオブジェクトで状態管理する
- 表示と更新関数が分離しているので、それぞれ別コンポーネントへ渡せる


#### 書きずらいポイント１
cssのclass定義がなぜか`className`

```jsx
// タイポじゃないです。classNameでスタイルのクラスを定義します。
<div className="App">classにしてくださいよ〜〜（泣）</div>
```

#### 書きずらいポイント２
styleがなぜかキャメルケース

```jsx
<div style={{ textAlign: "center" }}>スネークケースで良くない？？？</div>
```

**まとめ**
- スタイルの定義は書きずらい気がする
- 慣れのような気もする


### Reactは大規模開発で役立つんだ、公式もそう言ってる

らしいです。

[Reactの流儀](https://ja.reactjs.org/docs/thinking-in-react.html#and-thats-it)


## 総括

- 役割分担がかっちりしていてReact楽しい！
- 初学者はReactの思想を理解するのが大変かも


そして、Reactの大まかな考えや書き方のクセを理解するには公式チュートリアルが最適です！
公式最高！！みんなもやろう！！！

**公式チュートリアル**
https://ja.reactjs.org/tutorial/tutorial.html