React入門 -なぜReactを使うのか-

# はじめに
私がReactに出会い１年程度経過し、React自体にも大きな変化がありました。今回は、Reactの**良さを知ってもらいたい**と思い、筆を取りました。
また、改めて自分の中のReactの知識を整理しようというのがサブ目標です。何回かに分けて**1つのアプリを作れる程度**までを記事にまとめていきたいと思ってます。

筆者のステータスは以下の通りです

- React・[Next.js](https://nextjs.org/)を使って簡単なアプリを作ったことがある
- アルバイトでSpringを使ったwebアプリの開発をしている**（フロントはjQueryゴリゴリ）**


# Reactに出会って使用するに至った経緯

**概略: jQueryで[地獄](https://qiita.com/jirokun/items/8f19ef3e2ecf567f2ddb)を見たためReactに救いを求めました。**

前述の通りjQueryを良く使用していて基本は問題なかったのですが、画面項目が増え動きがリッチになるにつれ実装難易度やメンテナンス性に限界を感じてきました。
そこでたまたま出会ったのがReactでした。しかし、調べてみても*「MVCのVのみを担当するフレームワークで ──」「仮想DOMが──」*などと説明されていても「は？」って感じで、イマイチどういったモノなのか掴めずにいました。
しかし実際に使ってみると、実にシンプルなフレームワーク/ライブラリであり、悩みを解決してくれる存在であることがわかりました。元々JSが好きだったのもありとても馴染みやすかったです。

# Reactとは

[公式ドキュメント](https://reactjs.org/)には以下のように紹介されてます。
> A JavaScript library for building user interfaces
> ユーザインターフェース構築のための JavaScript ライブラリ

これだけではわからないので、主な機能の説明と実装例を用いて紹介していきたいを思います。

## Reactを使うと何がいいのか？
こちらも公式ドキュメントのトップから抜粋

1. *Declarative (宣言的なView)*
1. *Component-Based (コンポーネントベース)*

もう1つ「*Learn Once, Write Anywhere (一度学習すれば、どこでも使える)*」ということが挙げられていますが、これは一旦スルーで。

### Declarative (宣言的なView)
まず「宣言的」って何？というとこですね。
Reactで実装する際に私たちが実装するのは**「ある状態において何が表示されるべきか」**です。
*「この値をここに表示して」*、*「この場合はこっちを表示して」*というのをただただ**宣言**していけば良いわけです。

そしてその宣言通りに効率良くUIの更新（DOMの操作）をする必要があります。
そこで登場するのが**仮想DOM**です。仮想DOMは通常のDOMと同じツリー構造をとります。
仮想DOMが構築し直されると、差分のみが実際のDOMに反映される、といった具合です。

<img width="400" alt="v-dom.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258777/0b7f074f-69cc-42d9-92c5-348f65367d35.png">

仮想DOMの構築はサーバーサイドレンダリング(SSR)でテンプレートエンジンを使ってHTMLを生成するのに良く似ています。SSRでの描画で画面の値が不整合になったなんていう記憶はないので、それに近い方法を取れる仮想DOMを使わない手はありません。
加えて、必要な箇所のDOMの更新しか行われないため、下手なピュアのJSよりも**パフォーマンスが向上**します。

### Component-Based (コンポーネントベース)
ReactではUIの状態、見た目、動きを**コンポーネント**という単位で分割します。単純な入力欄からページまで全てをコンポーネントとみなします。コンポーネントを組みわせていくことでUIを構築していきます。
分割することで再利用が可能になり、全体的な見た目の統一感を生みます。

コンポーネントは**自身の状態を管理**し、**見た目と振る舞い**を定義します。そのため状態をDOMに置くことがなくなります。DOMにある値はどこからでも変更可能ですが、コンポーネントの状態はアクセスできるスコープが限られるので**状態の遷移が追いやすくなります**。

# Reactを書いてみる

## 九九を表示するアプリを考える

1. 何の段を表示させるかを入力する
1. 入力された段の九九の表を表示する

### jQueryの場合

Reactで書く前に比較対象としてjQueryを使った場合の実装をのせておきます

<p class="codepen" data-height="450" data-theme-id="0" data-default-tab="html,result" data-user="nabekou29" data-slug-hash="vYYZrQb" style="height: 450px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="kuku_jQuery">
  <span>See the Pen <a href="https://codepen.io/nabekou29/pen/vYYZrQb">
  kuku_jQuery</a> by nabekou (<a href="https://codepen.io/nabekou29">@nabekou29</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

data属性にかける値を持たせておいて、値が入力された際に、data属性のあるtdタグのテキストを書き換えていく感じです。

### Reactの場合

こちらがReactでの実装です。説明しやすさも考えてTypeScriptで書いてます。

<p class="codepen" data-height="450" data-theme-id="0" data-default-tab="js,result" data-user="nabekou29" data-slug-hash="ZEEyjpv" style="height: 450px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="kuku_React">
  <span>See the Pen <a href="https://codepen.io/nabekou29/pen/ZEEyjpv">
  kuku_React</a> by nabekou (<a href="https://codepen.io/nabekou29">@nabekou29</a>)  
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#### 解説

```コンポーネントの定義.tsx
const App: React.FunctionComponent<{defaultValue: number}> = ({defaultValue}) => {...}
```
この関数がコンポーネントです。(Classで定義する方法もあります。)
属性を引数に受け取ることができます。

```状態を扱う.tsx
const [num1, setNum1] = React.useState(defaultValue);
```
`React.useState`を使うことでこのコンポーネントで状態を持つことができます。
`num1`が状態、`setNum1`が`num1`を更新するための関数です。`setNum1`を通して値を更新することでReactに値が変わったことを知らせています。

```tsx:JSX.tsx
return (
  <div>
    <input type="number" value={num1} onChange={handleNum1Change} />の段
    <table>
      <tbody>
        <tr><th>1</th><td>{1 * num1}</td></tr>
        {/* 省略... */}
      </tbody>
    </table>
  </div>
);
```
関数のコンポーネントでは、**React要素**を`return`します。React要素は**JSXにより作成可能**です。コンパイルすることでReact要素を作成する関数に変換されます。(変換後はCodePenの「View Compiled」ボタンから確認できます)。
このHTMLっぽい書き方がJSXです。あくまでそれっぽいだけなので、本来存在しない属性や一部名前が変わっている属性が存在します。JSXのなかで`{}`で囲まれた中にJSを書くことが可能です。当然そのJS内でもJSXを書けます。

```データバインディング.tsx
const handleNum1Change = (event: React.ChangeEvent<HTMLInputElement>) => { 
  setNum1(Number(event.target.value));
}
```
値を入力した時に`num1`を更新します。`setNum1`を使って更新することで表の値が更新されます。


```tsx
ReactDOM.render(
  <App defaultValue={1}/>,
  document.getElementById('app')
);
```
React要素を`#app`に描画しています。

#### ちなみに

```tsx:before.tsx
<table>
  <tbody>
    <tr><th>1</th><td>{1 * num1}</td></tr>
    <tr><th>2</th><td>{2 * num1}</td></tr>
    <tr><th>3</th><td>{3 * num1}</td></tr>
    ...
    <tr><th>9</th><td>{9 * num1}</td></tr>
  </tbody>
</table>
```
HTMLに寄せて書きましたが、Arrayを用いて以下のように書くことが出来ます。

```tsx:after.tsx
<table>
  <tbody>
    {
      [1, 2, 3, 4, 5, 6, 7, 8, 9].map(num2 => (
        <tr key={num2}><th>{num2}</th><td>{num1 * num2}</td></tr>
      ))
    }
  </tbody>
</table>
```

### 比べてみる

1. *Declarative (宣言的なView)*
1. *Component-Based (コンポーネントベース)*

上の2つを意識して比べてみようと思います

#### 宣言的なView 的には？
特に`<td>{num1 * num2}</td>`のところがとてもわかりやすくなっていると思います。表に何が表示されるかがより明らかになりました。
また、更新がとても楽になっています。jQueryでは各`td`要素にアクセスして計算・更新をしていましたが、Reactでは`num1`を更新するだけで表の値が更新されています。

#### コンポーネントベース 的には？
見た目と動きが一体となったことで、状態の変化がどのように行われて、どういった作用をもたらすのかがぱっと見で分かるようになりました。JSとHTMLを行ったりきたりする必要が無くなりました。
さらに、変にセレクタを書いたりする必要性が無くなりました。どうせ密な結合になるならこっちの方がわかりやすいと思います。

# おわりに
Reactは学習コストが重いと良く言われている気がしますが、覚えることは圧倒的に少ないです。ただJSに対する知識がそれなりに求められるので、そこが難しいところなのかなと思います。Hooksの登場で書きやすさもかなり向上したので、これからも周りに布教していきたいと思います。
次はもう少し実装よりの話をする予定です。

# 参考
[React公式](https://ja.reactjs.org/)
[Reactを使うとなぜjQueryが要らなくなるのか](https://qiita.com/naruto/items/fdb61bc743395f8d8faf)
[ReactとVueのどちらを選ぶか](https://qiita.com/yoichiwo7/items/236b6535695ea67b4fbe)
[フロントエンドのコンポーネント設計に立ち向かう](https://qiita.com/seya/items/8814e905693f00cdade2)