Reactチュートリアルをやってみて分かったVue.jsとの違い

## 背景
筆者は実務で約1年半Vue.jsの開発をしています。Reactは記事でも見ることが多く、SPAといえばReactが一番に出てくるけれど、Reactを一才触ったことがなかったです（結局リアクティブだからそんな違いはないだろうと思うのもあってあまり触っていなかった）。とはいえ、よく聞くReactを一切触っていないのも怖く、その勉強がてらチュートリアルをやってみました。以下の比較は主に、Vue.js options API と React Hook を比較しています。

筆者はReactについてほとんど知らないです。（クラスコンポーネントと関数コンポーネントの違いを最近知ったくらい）

Reactのチュートリアルが新しくなっていました。React hookを前提とした内容になっています。

[チュートリアル：三目並べ – React](https://ja.react.dev/learn/tutorial-tic-tac-toe)


## 親コンポーネントのデータ書き換え

Vue.jsで親コンポーネントのデータを子コンポーネントから変更する際は `emit` を使用してデータを書き換えます。一方でReactでは、`prop`でデータを書き換える無名関数（クロージャー）を渡すことでデータを書き換えます。Vue.jsでは、`prop`で無名関数を渡すことは、コンポーネントの依存性が高まるため推奨されていません。

<details><summary>比較コード（親コンポーネントのcountを子コンポーネントから増加させる）</summary><div>
    

```javascript:vue
const ParentComp = {
    template: `
      <child-comp
        :count="count"  
        @set-count="count + 1"  
      ></child-comp>
    `,
    data() {
      return {
        count: 0
      }
    },
  
    components: [ChildComp]
  }
  
  const ChildComp = {
    props: ["count"],
    emits: ["setCount"],
    template: `
      <button @click="$emit('setCount')">
              Clicked {{ count }} times
      </button>
    `
}
```
    
```javascript:react
function ParentComp() {
    const [count, setCount] = useState(0);
  
    function handleClick() {
      setCount(count + 1);
    }
  
    return (
        <div>
          <ChildComp count={count} onClick={handleClick} />
        </div>
    );
  }
  
  function ChildComp({ count, onClick }) {
    return (
        <button onClick={onClick}>
          Clicked {count} times
        </button>
    );
  }
```
</div></details>

## 繰り返しの表示

Reactでは、JSXと言うマークアップ構文を使用することで簡単にテンプレートを変数に入れることができ、それを表示することができます。Vue.jsでは、template内でfor文を書いて実装します。React同じようにやろうと思えばできますが無駄な処理が多くなります。

<details><summary>比較コード（食べ物がリストで並んでいるコンポーネント）</summary><div>

```javascript:vue
const ProductsComp = {
  template: `
    <ul>
      <li v-for="product in products" :key="product.id">
        {{ product.name }}
      </li>
    </ul>
  `,
  data() {
    return {
      products: [
        {id: 1, name: "apple"},
        {id: 2, name: "banana"}
      ]
    }
  },
}
```

```javascript:react
function ProductsComp() {
  const products = [
    {id: 1, name: "apple"},
    {id: 2, name: "banana"}
  ]  
  const listItems = products.map(product =>
      <li key={product.id} >
        {product.name}
      </li>
  );
  return (
      <ul>{listItems}</ul>
  );
}
```
</div></details>

## マークダウン構文

Vue.jsでは、bindを使用してtemplate内に表示したいマークアップを書きます。Reactでは、JSXと言うマークアップ構文を使用することで、関数コンポーネントがマークアップを返却することができ、より自由度が増しているように感じました。

<details><summary>比較コード（視聴済みか未視聴かで表示するテキストを切り替える）</summary><div>
    
```javascript:vue
const TitleComp = {
  template: `
    <template v-if="isWatched">
      <p>watched</p>
    </template>
    <template v-else>
      <p>unwatch</p>
    </template>
  `,
  data() {
    return {
      isWatched: false
    }
  }
}
```

```javascript:react
function TitleComp() {
  const [isWatched, toWatched] = useState(false);

  if (isWatched) {
    return (
        <p>watched</p>
    )
  } else {
    return (
        <p>unwatch</p>
    )
  }
}
```
</div></details>

# やってみた感想

Vue.jsをある程度やっていると、参入障壁は非常に低いと思いました。コンポーネント間のデータのやり取りの考えがわかっていると特に困ることはないと思います。

チュートリアルの内容とは関係ないのですが、ページの表示が早く感じました。Next.jsを使用しているので、SSG機能を使用しているかな？Next.jsを書いたことがないので今後やってみたい。

Qiitaの折りたたみが書きずらすぎた。