Vue.jsからReactをなんとなく理解する

## はじめに

Vueは触ったことあるけどReact触ったことがなくて欠片もわからん！！
でもプロジェクトにjoinされた！ ワグナス！ 書き方すらわからんぞどうすればいい！
そんな2か月前の私のような皆さんに向けたn番煎じ記事がこちらです。

## そもそもReactとは

よく聞く話なのでご存知な方も多いとは思いますが、ReactはJSの**ライブラリ**です。UIを構築するためのJSライブラリです。
Vue.jsがフレームワークという立ち位置を取っているのに対し、Reactはライブラリという立ち位置を維持しています。

けっこう流されがちな話なのですが、Vueを触ったことがあるけどもReact触ったことがない人には、個人的にはここがおそらく一番重要な話だと考えています。
ざっくりいうと、ReactはVueほどよしなに色々してくれないわけです。これを自由度が高いと取るか不便と取るかは個々人の価値観に寄るような気がするのですが、よくVueの方が初学者の敷居が低いと言われる本質はここにある気がします。

## ビルドツール

Vueの場合は8割くらいの人がvue-cliを使っているかと思います。
Reactの場合は、公式が学習またはSPA開発にはcreate-react-appを使うようにと言っています。

以下からはnpmを利用するので、yarn使いの皆さんは良しなに読み替えてください。

インストールと初期状態構築のためのコマンドは以下の通りです。

```bash
npx create-react-app app-name
```

`npx`はtypoではなく`npm`が持つコマンドです。直下のnode_modulesにインストール済みのパッケージを叩いたり、まだ未インストール状態のパッケージを自動で一時的に引っ張ってきて叩いてくれたりするコマンドです。
今回の場合だと、最新版の`create-react-app`を一時的にインストールして実行しています。

これで指定したアプリ名のディレクトリが作成されるので、あとはいつものごとくcdして`npm start`です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532032/eeadb01b-1592-3524-4c8d-a569a4cbda0d.png)

ちなみに、vueとは異なり勝手にブラウザが立ち上がります。

さて、ここでしこたま`vue-cli`を触ってきた方ならなんとなく違和感を感じるかと思います。
`vue-cli`で初期状態を構築する場合のコマンドは以下のようになります。

```bash
npm install -g @vue/cli
vue create app-name
```

`vue-cli`の場合は、わざわざグローバルインストールを行ってから実行する必要があります。
厳密に言うと実は`npx @vue/cli create app-name`みたいなこともできるのですが、公式としては上記のコマンドの方をまず紹介する程度にはグローバルインストールを推奨しているようです。

推測ですが、この辺りに差がある理由はライブラリとフレームワークの在り方の違いが原因のような気がします。

え、Vite？ あれはまあ、Reactも使えるので今回の話からは除くということで。

## 記載方法

以下からは、VueとReactの具体的な書き方の違いに触れていきます。

### コンポーネント全体の違い

#### Vue.jsの場合

Vueの場合、以下のような形でコンポーネントを記載したかと思います。

```vue
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

主に三つのパーツから構成されており、上から順に

- マークアップを記載するtemplate
- ロジック周りを記載するscript
- CSSを記載するstyle

となります。

#### Reactの場合

一方、Reactの場合はあくまでライブラリなので、一般的なJSの構文に合わせた記載をします。ただし、利用する構文はJSの拡張であるJSXを利用するので、ファイルの拡張子等は`hoge.jsx`になります。
(create-react-appはデフォルトでjsxの記法で書かれた`hoge.js`ファイルをjsxとして認識してくれるので、`hoge.js`のままでも一応問題なく動作します)

書き方としては関数型とclass型の二種類があり、公式にはReactHooksの利用推進目的で関数型の利用が推奨されているように感じます。
書き方としては以下の通りです。
(今から記載するのはcreate-react-appのデフォルトページです。CSSinJSやCSS modulesに関しては一旦置いておきます)

```React
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

```

見ての通り、HTMLをreturnする関数を記載するイメージです。ほぼJSに近い感覚で記載できます。

### data

#### Vueの場合

Vueではコンポーネント内で値を管理する場合、以下のような書き方をしたかと思います。

```vue
<template>
  <p>value {{ hoge }}</p>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      hoge: 0
    }
  }
}
</script>
```

#### Reactの場合

一方で、Reactの関数型の場合は、React Hooksというものを用いて値の管理を行います。

```react
import React, { useState } from 'react';

function App() {
  const [hoge, setHoge] = useState(0)
  return (
    <p>hoge { hoge }</p>
  );
}

export default App;

```

名前からなんとなく想像がつくと思うのですが、useStateでvueで言うdataの対象となるものを宣言、このuseStateの引数がhogeの初期値となります。
hogeの更新を行う場合は、`setHoge(hoge+1)`以下のような形で行います。
また、テンプレート構文の{}の数が一組少なくなっています。

### method

#### Vueの場合

Vueの場合、methods内に記載します。

```vue
<template>
  <button @click="logHoge">click me &amp; look at console </button>
</template>

<script>
export default {
  name: 'App',
  methods:{
    logHoge(){
      console.log('hoge');
    }
  }
}
</script>
```

#### Reactの場合

Reactの場合、普通のJSと同じく関数を宣言して使用します。
※若干話がそれますが、コンポーネントの宣言時やmethodの宣言時にアロー関数って使ってもいいんですかね。Vueで不用意にアロー関数を使って痛い目を見たことがあるので少々気になります。

```react
import React from 'react';

function App() {
  function logHoge() {
    console.log('hoge')
  }
  return (
    <button onClick={logHoge} > click me &amp; look at console </button >
  );
}

export default App;
```

このあたりライブラリとフレームワークの違いが出ている感じがしますね。

### computed

React的には類似するであろう機能は確認できませんでした。
React.PureComponentやReact.memo等で近いようなことが行えるような気はするのですが、パフォーマンス最適化を意識する場合のみ使用するべき等の記載があるため避けたほうが良い気がします。
ReactHooksを使用する場合は、useEffectで第二引数を指定した場合やuseMemo等で近いことが可能です。
そのあたりの最適化をよし何してくれることに関しては、Vue.js自体がReactに対する強みとして挙げているので、Reactではなかなか難しいのかもしれません。

## ライフサイクル

Reactのライフサイクルに関しては[こちら](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)に記載されています。
Vueと比較して非常にすっきりしていることが見て取れます。裏を返すとできることが少ないとも言えますが、個人的にVueのライフサイクルメソッドで実際に利用するものは限られている印象なので、シンプルで余計なものが少ない設計ともいえるでしょう。
関数型でライフサイクルを実装する場合は、constructorをuseStateで、componentDidMountやcomponentDidUpdate、componentWillUnmountをuseEffectで置き換えることが可能です。


以上、必要がありそうなら追加します。