3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ReactとVueの書き方の違い:同じ画面でも読む順番が変わる

3
Posted at

はじめに

この記事では、React と Vue の書き方の違いを、コードを読む順番から整理します。

Vue と React の比較では、テンプレートと JSX、v-if と条件分岐、v-modelvalue + onChange のような個別記法がよく話題になります。

ただ、実務でコードを読むときに効いてくるのは、記法そのものだけではありません。

同じ画面を作っても、Vue と React では次の感覚がかなり違います。

  • どこから読み始めるか
  • 状態と表示の関係をどこで見るか
  • イベント処理をどこで追うか
  • 表示用の値をどこで作るか

この記事では、個別記法の対応表ではなく、「同じ画面を書いたときに、どう読み味が変わるか」を整理します。

先に結論

ざっくり言うと、次の違いです。

  • Vue はテンプレートから画面の形を読みやすい
  • React は JavaScript / TypeScript の処理の流れを追いやすい

Vue は、template を見ると画面の構造が分かりやすいです。
HTML に近い形で、条件分岐、繰り返し、イベント、入力が並びます。

一方で React は、コンポーネント関数の中で状態、派生値、イベント、表示をまとめて扱います。
最初は JSX に慣れが必要ですが、慣れると「この関数の中で何が起きているか」を追いやすいです。

どちらが常に良いという話ではありません。

Vue は画面の形を先に見たいときに読みやすいです。
React は処理の流れを先に見たいときに読みやすいです。

この記事で扱わないこと

既に別の記事で整理している内容とは、なるべく重ならないようにします。

この記事では、次の話は深掘りしません。

  • v-ifv-for を React でどう書くか
  • v-modelvalue + onChange の細かい違い
  • Composition API と React Hooks の違い
  • computedwatch の使い分け

ここでは、もっと上の層として「コード全体をどう読むか」に絞ります。

読み始める場所が違う

Vue と React では、最初に見る場所が変わります。

Vue では、まず template から読むことが多いです。
画面に何が表示されるかを先に見て、その後で script setup 側の状態や関数を確認します。

一方 React では、コンポーネント関数を上から読むことが多いです。
useState で状態を確認し、派生値を見て、最後に return の JSX を読みます。

つまり Vue は「画面から処理へ」、React は「処理から画面へ」読む感覚に近いです。

この記事の「読む順番」とは、この最初に見る場所の違いを指しています。

同じ画面を Vue で書く

例として、ユーザー一覧を絞り込み、選択したユーザー名を表示する小さな画面を考えます。

Vue では次のように書けます。

<script setup lang="ts">
import { computed, ref } from "vue"

type User = {
  id: number
  name: string
}

const users = ref<User[]>([
  { id: 1, name: "山田" },
  { id: 2, name: "佐藤" },
  { id: 3, name: "鈴木" },
])

const keyword = ref("")
const selectedId = ref<number | null>(null)

const filteredUsers = computed(() => {
  return users.value.filter((user) => user.name.includes(keyword.value))
})

const selectedUser = computed(() => {
  return users.value.find((user) => user.id === selectedId.value)
})

const selectUser = (id: number) => {
  selectedId.value = id
}
</script>

<template>
  <section>
    <input v-model="keyword" placeholder="名前で検索">

    <ul>
      <li v-for="user in filteredUsers" :key="user.id">
        <button @click="selectUser(user.id)">
          {{ user.name }}
        </button>
      </li>
    </ul>

    <p v-if="selectedUser">
      選択中: {{ selectedUser.name }}
    </p>
  </section>
</template>

Vue の場合、まず template を見ると画面の構造が分かります。

  • 入力欄がある
  • 一覧を表示している
  • ボタンを押すと選択する
  • 選択中のユーザーを表示している

画面の形を先に掴み、その後で script setup 側を見ると、状態や計算値の意味を確認できます。

この読み方ができるのは Vue の強みです。
UI の見た目とテンプレートの形が近いため、画面構造を追いやすいです。

同じ画面を React で書く

React で書くと、次のようになります。

import { useState } from "react"

type User = {
  id: number
  name: string
}

const users: User[] = [
  { id: 1, name: "山田" },
  { id: 2, name: "佐藤" },
  { id: 3, name: "鈴木" },
]

export function UserList() {
  const [keyword, setKeyword] = useState("")
  const [selectedId, setSelectedId] = useState<number | null>(null)

  const filteredUsers = users.filter((user) => user.name.includes(keyword))
  const selectedUser = users.find((user) => user.id === selectedId)

  return (
    <section>
      <input
        value={keyword}
        placeholder="名前で検索"
        onChange={(event) => setKeyword(event.target.value)}
      />

      <ul>
        {filteredUsers.map((user) => (
          <li key={user.id}>
            <button onClick={() => setSelectedId(user.id)}>
              {user.name}
            </button>
          </li>
        ))}
      </ul>

      {selectedUser && (
        <p>
          選択中: {selectedUser.name}
        </p>
      )}
    </section>
  )
}

React の場合、コンポーネント関数の中に状態、派生値、イベント、表示がまとまっています。

読むときは、だいたい次の順番になります。

  1. useState で何の状態を持っているかを見る
  2. filteredUsersselectedUser で何を計算しているかを見る
  3. return の JSX でどう表示しているかを見る
  4. イベントでどの state を更新しているかを見る

Vue と比べると、HTML 的な見た目からは少し離れます。
ただし、処理は JavaScript / TypeScript の流れとして追いやすいです。

filteredUsers は配列の filter です。
selectedUser は配列の find です。
ボタンを押したら setSelectedId を呼びます。
入力が変わったら onChange でイベントを受け取り、setKeyword で state を更新します。

専用記法を別に読むというより、JavaScript の処理として読めます。

派生値の置き方が違う

状態から作る値の置き方にも違いがあります。

Vue では、状態から作る値を computed として明示します。

const filteredUsers = computed(() => {
  return users.value.filter((user) => user.name.includes(keyword.value))
})

filteredUsers は、userskeyword から作られる値です。
Vue では、このような値を computed にすることで「これは状態から作る派生値です」と宣言します。

React では、単純な派生値ならコンポーネント関数内の普通の変数として書くことが多いです。

const filteredUsers = users.filter((user) => user.name.includes(keyword))

React では、コンポーネントがレンダリングされるたびに関数が実行されます。
その中で users.filter(...) を実行し、今回の表示に必要な値を作ります。

Vue は派生値であることを明示する感覚が強いです。
React はレンダリング中に計算される値として、JavaScript の変数に自然に置く感覚があります。

もちろん React でも、計算が重い場合や参照を安定させたい場合は useMemo を使います。
ただ、この例のような小さな絞り込みでは、まず普通の変数として読む方が自然です。

イベント処理の追い方も違う

イベント処理も、どこを見ると理解しやすいかが変わります。

Vue では、テンプレート上にイベントを書きます。

<button @click="selectUser(user.id)">
  {{ user.name }}
</button>

この行を見ると、ボタンを押したときに selectUser(user.id) が呼ばれることが分かります。
処理の本体を知りたい場合は、script setup 側の関数定義を見に行きます。

const selectUser = (id: number) => {
  selectedId.value = id
}

Vue は、テンプレートで「何が起きるか」を見て、必要に応じて処理本体へ移動する読み方になります。

React では、JSX のその場で state 更新まで見えることがあります。

<button onClick={() => setSelectedId(user.id)}>
  {user.name}
</button>

この例では、クリックしたら setSelectedId(user.id) を呼ぶことが JSX 上で分かります。
関数を別に切り出していないため、イベントから state 更新までの距離が短いです。

Vue は画面上のイベント名から処理へ進みます。
React は JSX の中で、イベントと更新処理をまとめて読むことが多いです。

Vue は画面の形が先に見える

Vue の読みやすさは、画面の形が先に見えるところにあります。

<input v-model="keyword" placeholder="名前で検索">

この1行を見ると、入力欄と keyword がつながっていることが分かります。

<li v-for="user in filteredUsers" :key="user.id">

この行を見ると、filteredUsers を一覧表示していることが分かります。

Vue のテンプレートは、UI の構造を読むにはかなり素直です。
デザイナー寄りの人や、HTML の見た目から入りたい人には読みやすいです。

一方で、処理の詳細は Vue の記法を理解している前提になります。

  • v-model が何を省略しているのか
  • v-for がどのように配列を描画するのか
  • @click が何のイベントを扱うのか
  • computed がいつ再計算されるのか

このあたりを知らないと、短く見えるぶん、逆に裏側を想像しにくいことがあります。

React は処理の流れが先に見える

React の読みやすさは、処理の流れが JavaScript / TypeScript として見えるところにあります。

const filteredUsers = users.filter((user) => user.name.includes(keyword))

これは普通の配列操作です。

onChange={(event) => setKeyword(event.target.value)}

これは入力イベントを受け取り、state を更新しています。
値の入口が event.target.value で、更新先が setKeyword だとその場で分かります。

{filteredUsers.map((user) => (
  <li key={user.id}>
    {user.name}
  </li>
))}

これは配列を JSX に変換しています。

React は書く量が増えやすいです。
ただし、処理が見えているため、どこで値が変わるのかは追いやすいです。

特に TypeScript を普段から書いている人にとっては、React の方が「知らない専用記法」が少なく感じることがあります。

書き方の違いは責務の置き場所の違い

Vue と React の書き方の違いは、単に記法の違いではありません。

責務の置き場所が違います。

Vue は、テンプレートに UI の意図を置きます。

  • 表示する
  • 繰り返す
  • 条件で出す
  • イベントを受ける
  • 入力と値をつなぐ

React は、JavaScript / TypeScript の式として UI を組み立てます。

  • 配列を map する
  • 条件式で JSX を出す
  • イベントで state を更新する
  • state から表示を作る

Vue は UI 専用の読みやすさを作ります。
React は JavaScript の一貫性を保ちます。

この差が、書き味の違いとして出ます。

どちらが読みやすいかは場面で変わる

画面の構造をすぐ見たいなら、Vue は読みやすいです。

template を見れば、UI の骨格が分かります。
入力欄、一覧、条件表示、イベントがテンプレート上に並ぶため、画面の形を掴みやすいです。

一方で、状態の流れや値の変化を追いたいなら、React は読みやすいです。

コンポーネント関数の中で、state、派生値、イベント、JSX がつながっています。
JavaScript / TypeScript の関数として読めるため、ロジックの流れを追いやすいです。

特に、バックエンド寄りで TypeScript に慣れている人は、React の方が自然に感じることがあります。

Vue と React を比べると、Vue の方が短く見えることが多いです。

例えばフォーム入力では、Vue は v-model で短く書けます。
React は valueonChange を分けて書きます。

ただし、短いことと読みやすいことは同じではありません。

Vue の短さは、Vue がよくある処理を包んでくれているからです。
React の冗長さは、表示と更新を明示しているからです。
onChange から setKeyword までが見えるので、入力値がどこで state に入るかを追いやすくなります。

そのため、比較するときは次の問いで見る方が実務的です。

  • 初見で画面の形を掴みやすいのはどちらか
  • 値がどこで変わるか追いやすいのはどちらか
  • チームのメンバーが慣れているのはどちらか
  • TypeScript の知識をそのまま使いやすいのはどちらか
  • フレームワーク固有の作法をどこまで許容できるか

この観点で見ると、単純に「短いから Vue」「明示的だから React」とは言い切れません。

画面が大きくなると差が出る

小さいサンプルでは、Vue も React も大きな差はありません。
どちらのコードも短く、全体をすぐに読めます。

ただ、画面が大きくなると読み方の違いが効いてきます。

Vue は template を見れば UI の骨格を掴みやすいです。
入力欄、一覧、条件表示、イベントの位置が、画面に近い形で並びます。

一方で、処理が増えると script setup 側との往復が増えます。
テンプレートで見つけた filteredUsersselectUser の意味を、上の script まで戻って確認する場面が出てきます。

React は JSX と処理が同じ関数内にあるため、値の流れは追いやすいです。
状態、派生値、イベント、表示が同じスコープにあります。

一方で、JSX に条件分岐や map が増えると、見た目の構造は少し読みにくくなります。
JavaScript の式としては自然でも、HTML の骨格だけを眺めたいときには情報量が多くなります。

この差は、どちらが優れているかではありません。
画面構造を先に見たいのか、値の流れを先に見たいのかの違いです。

まとめ

React と Vue は、同じ画面を作れても、コードの読み方がかなり違います。

ポイントをまとめると次のとおりです。

  1. Vue はテンプレートから画面の形を読みやすい
  2. React は JavaScript / TypeScript の処理の流れを追いやすい
  3. Vue は UI 専用の記法で短く書ける
  4. React は状態更新や配列操作が明示的に見えやすい
  5. 比較するときはコード量ではなく、どこから読むと理解しやすいかを見るとよい

Vue は「画面をテンプレートとして整理して読む」感覚に近いです。
React は「関数の中で状態から UI を作る」感覚に近いです。

この違いを押さえると、Vue と React の書き方を単なる好みではなく、読み方の違いとして整理しやすくなります。

Vue と React の違いは、どちらが簡単かではなく、どこに読みやすさを置いているかの違いです。
Vue はテンプレートに読みやすさを置き、React は JavaScript / TypeScript の流れに読みやすさを置いています。

テンプレートと JSX の違いは「VueのテンプレートとReactのJSXは何が違うのか」で整理しています。
個別の記法の対応は「Vueの主要ディレクティブをReactで書くとどうなるか」も関連します。
フォーム入力の違いは「Vueのv-modelは便利だがReactのvalueとonChangeはなぜ分かりやすいのか」でも整理しています。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?