react.js(next.js)とvue.js(nuxt.js)の違いをソースで確認してみましょう


## 概要
最近人気のフロントエンドの言語である`react.js`, `vue.js`, `augular.js`があります
`angular.js`は下落傾向で、`react.js`と`vue.js`はほぼ同じように人気があります

この記事では、`react.js`と`vue.js`に対する違いと
`next.js`と`nuxt.js`に対する違いをソースで確認してみましょう

## next.jsとnuxt.jsって何？

`next.js`は`react.js`の`SSR(ServerSideRender)フレームワーク`です
`nuxt.js`は`vue.js`の`SSR(ServerSideRender)フレームワーク`です

`react.js`と`vue.js`は、基本的に`CSR(Client Side Render)`です

`CSR(Client Side Render)`の場合、検索エンジンに露出できない短所があり、
最初のスクリプトロード時間が長いという短所があります

`react.js`と`vue.js`のどちらも`BtoB`の場合、特別な問題はありませんが、
`BtoC`の場合、検索エンジンの露出が重要な要素となっているため、
結局は`webpack`をカスタマイズするか`next.js`と`nuxt.js`に変えることになります。

## プロジェクト作成の違い

```

yarn global add create-next-app
create-next-app next-tutorial
yarn dev
```

`next.js`の場合、`create-next-app`モジュールを利用してプロジェクトを作成します

```
yarn global add create-nuxt-app
create-nuxt-app nuxt-tutorial
yarn dev
```

`nuxt.js`の場合、`create-nuxt-app`モジュールを利用してプロジェクトを作成します

## component基本

`next.js`と`nuxt.js`はページディレクトリを利用してrouteします
基本的なコンポーネントソースの違いを確認してみましょう

#### next.js (react.js)
/pages/index.js

```react
import { useEffect } from "react"

const Home = () => {
  useEffect(() => {
    console.log('mounted')
    return () => {
      console.log('unmounted')
    };
  }, []);
  
  return (
    <div>
      hello next.js
    </div>
  )
}

export default Home
```

####  nuxt.js (vue.js)
/pages/index.vue

```vue
<template>
  <div>
    hello nuxt.js
  </div>
</template>

<script>
export default {
  mounted() {
    console.log('mounted')
  },
  unmounted() {
    console.log('unmounted')
  }
}
</script>

```

`react.js`の場合、`JSX`を使用してレンダリングします
`vue.js`の場合、`html`を使用してレンダリングします
ライフサイクルは文法は少し違いますが、構造はほとんど似ています

`react.js`の場合、`JSX`を学ぶ必要があるためパブリッシャーが作業が難しいため、
日本ではvue.jsが人気が高いと言われています

## component state

#### next.js (react.js)
/pages/index.js

```react
import { useState, useEffect } from "react"

const Home = () => {
  const [count, setCount] = useState(0)

  return (
    <div>
      count : {count}
    </div>
  )
}

export default Home
```

####  nuxt.js (vue.js)
/pages/index.vue

```vue
<template>
  <div>
    count : {{count}}
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  }
}
</script>
```

`react.js`の場合、react hooksであるuseStateを利用してstateを作成します
`vue.js`の場合、データ関数を利用してstateを作成します

`react.js`の場合、{}を利用して変数をレンダリングします
`vue.js`の場合、{{ }}を利用して変数をレンダリングします

## counter

#### next.js (react.js)
/pages/index.js

```react
import { useState, useEffect } from "react"

const Home = () => {
  const [count, setCount] = useState(0)

  const increaseCount = () => {
    setCount(count + 1)
  }

  const decreaseCount = () => {
    setCount(count - 1)
  }

  return (
    <>
      <div>
        count : {count}
      </div>
      <button onClick={increaseCount}>+</button>
      <button onClick={decreaseCount}>-</button>
    </>
  )
}

export default Home
```

####  nuxt.js (vue.js)
/pages/index.vue

```vue
<template>
  <div>
    <div>
      count : {{count}}
    </div>
    <button @click="increaseCount()">+</button>
    <button @click="decreaseCount()">-</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increaseCount() {
      this.count +=  1
    },
    decreaseCount() {
      this.count -= 1
    }
  }
}
</script>
```
react.jsの場合、`setState`を使用してstateをアップデートします
vue.jsの場合、`this`を使用してstateをアップデートします

react.jsの場合、コンポーネント内部にイベント関数を作成します
vue.jsの場合、methods内部にイベント関数を作成します

react.jsの場合、`onClick`プロパティを利用してバインディングします
vue.jsの場合、`@click`プロパティを利用してバインディングします

## childコンポーネントにsteteとイベント関数を伝達

#### next.js (react.js)
/components/sample.js

```react
const Sample = (props) => {
  return (
    <>
      <div>
        count : {props.count}
      </div>
      <button onClick={props.increaseCount}>+</button>
      <button onClick={props.decreaseCount}>-</button>
    </>
  )
}

export default Sample
```

/pages/index.js

```react
import { useState, useEffect } from "react"
import Sample from "../components/Sample"

const Home = () => {
  const [count, setCount] = useState(0)

  const increaseCount = () => {
    setCount(count + 1)
  }

  const decreaseCount = () => {
    setCount(count - 1)
  }

  return (
    <>
      <Sample 
        count={count}
        increaseCount={increaseCount}
        decreaseCount={decreaseCount}
      />
    </>
  )
}

export default Home
```


####  nuxt.js (vue.js)
/components/sample.vue

```vue
<template>
  <div>
    <div>
      count : {{count}}
    </div>
    <button @click="$emit('increase-count')">+</button>
    <button @click="$emit('decrease-count')">-</button>
  </div>
</template>

<script>
export default {
  props: ['count'],
  emits: ['increase-count', 'decrease-count']
}
</script>

```

/pages/index.vue

```vue
<template>
  <div>
    <Sample 
      :count="count"
      @increase-count="increaseCount()"
      @decrease-count="decreaseCount()"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increaseCount() {
      this.count +=  1
    },
    decreaseCount() {
      this.count -= 1
    }
  }
}
</script>

```

`react.js`の場合、propsを利用してchildコンポーネントにstateやイベント関数を伝達します
`vue.js`の場合、各属性を利用してchildコンポーネントにstateやイベント関数を伝達します

`react.js`の場合、すぐにバインディングして使用できます
`vue.js`の場合、$emitを利用してバインディングすると使用できます

## SSR function

#### next.js (react.js)
/pages/index.js

```react
const Home = ({data}) => {
  return (
    <>
      {data}
    </>
  )
}

Home.getInitialProps = () => {
  return { data: 'SSR' }
}

export default Home
```

####  nuxt.js (vue.js)
/pages/index.vue

```vue
<template>
  <div>
    {{data}}
  </div>
</template>

<script>
export default {
  asyncData() {
    return { data: 'SSR' }
  },
}
</script>
```

SSRフレームワークの場合、htmlが構成される前にデータをfetchできる関数を提供します

`next.js`の場合、`getInitialProps`を使用します
`nuxt.js`の場合`asyncData`を使います

## state 管理

vue.jsの場合、vuexを主に使います
![vuex.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/ecd94fe0-9e42-b882-6835-aa3d7c332234.png)

react.jsの場合、主にreduxを使用します
![redux-logo-landscape.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497528/2ff3d71d-576e-d4be-e250-c055a62a0e33.png)


## まとめ

最も人気のある言語を簡単に2つ比較してみました
ご覧のとおり `vue.js`も`react.js`もメカニズムは似ています
また`next.js`と`nuxt.js`もメカニズムが似ています
したがって、一つを勉強すれば他の言語も簡単にできます

皆さんは`vue.js`と`react.js`、どちらが好きですか？