ReactとVue.jsのデータバインディングの違いを実体験も踏まえ比較
はじめに
筆者の技術レベル:
- React: 約1年の開発経験
- Vue3: 管理画面の保守で約1年の経験
両方のフレームワークを実際に触った経験から、データバインディングの違いについて解説します。
データフローの基本的な違い
- React: 一方通行のデータフロー
- Vue: 一方通行と双方向バインディングの両方に対応
1. Reactの実装例(一方通行のデータフロー)
Reactでは親コンポーネントから子コンポーネントへstate関数を渡す方法を取ります。これが「一方通行のみ」と言われている理由です。
// React - 一方通行のデータフロー
const UserProfile: React.FC = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
return (
<div>
{/* 親から子へのデータフロー(一方通行) */}
<input
value={name}
onChange={(e) => setName(e.target.value)} // 明示的にsetterを呼ぶ必要
placeholder="名前"
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)} // 毎回イベントハンドラーが必要
placeholder="メール"
/>
<p>名前: {name}</p>
<p>メール: {email}</p>
</div>
);
};
2. Vue.jsの実装例(双方向バインディング対応)
<!-- Vue.js - v-modelで双方向バインディング -->
<template>
<div>
<!-- 双方向バインディング - 自動で同期 -->
<input v-model="name" placeholder="名前" />
<input v-model="email" placeholder="メール" />
<p>名前: {{ name }}</p>
<p>メール: {{ email }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const name = ref('')
const email = ref('')
// v-modelが自動でname.value = inputの値を更新してくれる
</script>
実体験での感想
私自身、Vueの実装時は双方向バインディングが自動同期だったことを深く意識していませんでした(バックエンドが充実していたプロジェクト&管理画面だったので、フロントエンドで複雑な処理をしなかった)。
その後Reactを初めて触った時、Vueに比べてやけにソース記述量が多いと感じた部分の一つがこのデータバインディングでした。
両方経験して感じること
ただ、両方を経験した身としては、以下の理由により狙った挙動を実現できるReactの方が安心だと感じています。
双方向バインディングのデメリット
1. 意図しない副作用・デバッグの困難さ
Vue.jsの問題例:
<!-- Vue.js - 意図しない更新の例 -->
<template>
<div>
<!-- 複数の入力が同じデータを参照 -->
<input v-model="user.name" placeholder="名前" />
<input v-model="user.name" placeholder="表示名" />
<!-- どこで値が変わったか追跡が困難 -->
<ChildComponent v-model="user.name" />
<AnotherChild :data="user" />
</div>
</template>
<script setup>
// どのコンポーネントがuser.nameを変更したかわからない
const user = reactive({ name: '' })
</script>
Reactの解決例:
// React - 明示的な更新で追跡しやすい
const UserForm: React.FC = () => {
const [user, setUser] = useState({ name: '' });
const handleNameChange = (newName: string, source: string) => {
console.log(`名前が${source}から変更されました:`, newName); // デバッグしやすい
setUser(prev => ({ ...prev, name: newName }));
};
return (
<div>
<input
value={user.name}
onChange={(e) => handleNameChange(e.target.value, 'メイン入力')}
/>
<input
value={user.name}
onChange={(e) => handleNameChange(e.target.value, '表示名入力')}
/>
</div>
);
};
まとめ
- Vue.js: 初心者には実装しやすい、記述量が少ない
- React: 明示的で予測しやすい、大規模開発での保守性が高い
とまあReact寄りで比較してしまったが、Vueでも意図的に親→子のみにしたり、デバッグも拡張機能で便利なものがあるかも。その辺はまた後日調べます。