はじめに
この記事では、Vue の Composition API と React Hooks の違いを整理します。
Vue 3 と React は、どちらも関数ベースでロジックを組み立てる感覚があります。
そのため、Composition API と Hooks は似て見えます。
実際、次のような共通点があります。
- 状態を持てる
- ロジックを分割できる
- 関心ごとごとにまとめやすい
ただし、似ているのは表面だけで、使っていて感じる書き味はかなり違います。
先に結論
先に結論を書くと、次の違いです。
- Vue の Composition API は reactivity の仕組みが前面にある
- React Hooks は render と state 更新の仕組みが前面にある
つまり、
- Vue は「リアクティブな値を組み立てる」感覚
- React は「再レンダリングされる関数の中で state を扱う」感覚
です。
似ているところ
まず、似ているところから見ます。
Vue:
import { ref } from "vue";
const count = ref(0);
const increment = () => {
count.value++;
};
React:
import { useState } from "react";
const [count, setCount] = useState(0);
const increment = () => setCount((count) => count + 1);
どちらも、
- 状態を持つ
- 更新関数を書く
- UI に反映される
という意味では近いです。
Vueはrefやreactiveが中心になる
Vue の Composition API では ref や reactive が中心です。
const name = ref("名無し");
const form = reactive({
email: "",
age: 0,
});
Vue では「リアクティブな値」を先に作る感覚が強いです。
そのため、ロジックを読んでいても、
- この値は reactive か
-
refか -
computedか
のように、リアクティブシステムの種類を意識する場面が多いです。
Reactはstateとrenderの関係が中心になる
React では useState を中心に state を扱い、必要なときだけ useEffect で外部同期を扱います。
const [name, setName] = useState("名無し");
React で意識するのは、次の流れです。
- state が変わる
- コンポーネントが再レンダリングされる
- JSX が再評価される
Vue より「再レンダリングされる関数」という感覚が強いです。
computed と useMemo は似て見えるが同じではない
Vue の computed と React の useMemo は似て見えますが、感覚は違います。
Vue:
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
React:
const fullName = useMemo(() => `${firstName} ${lastName}`, [firstName, lastName]);
useMemo は、値の再計算結果をメモしておき、依存配列の中の値が変わったときだけ再計算するためのフックです。
そのため、毎回の render で重い計算をやり直したくないときや、参照の安定性を保ちたいときに使います。
React では、派生値はまず render 中にそのまま計算し、重さや参照安定性が問題になるときに useMemo を検討する形が基本です。
Vue の computed は、リアクティブな値から派生値を作る自然な流れです。
React の useMemo は、再計算コストや参照安定性を意識した最適化の文脈が混ざります。
そのため、React では computed のような気軽さで useMemo を増やすと、かえって読みにくくなることがあります。
watch と useEffect も発想が違う
Vue:
watch(searchWord, () => {
fetchList();
});
React:
useEffect(() => {
fetchList();
}, [searchWord]);
見た目は近いですが、ここも発想が違います。
- Vue の
watchは値の変化を監視する - React の
useEffectはレンダー後の副作用を扱う
Vue の watch は「この値が変わったらこの処理を動かす」という読み方をしやすいです。
一方で React の useEffect は、単純な監視フックとして使うより、外部システムと同期する境界として考えた方が実態に近いです。
React では、render 中に計算できることや、イベントハンドラで直接処理できることまで useEffect に入れると、かえって回りくどくなりやすいです。
そのため useEffect は「値が変わったら何かする便利フック」というより、「render の外にあるものとつなぐ場所」と捉えた方が整理しやすいです。
React の useEffect は便利ですが、慣れるまでは「これは監視なのか、副作用なのか、初回実行なのか」で混乱しやすいです。
この点では、Vue の watch のほうが意図が分かりやすい場面もあります。
Reactのほうが分かりやすいと感じるのはどこか
それでも React のほうが分かりやすいと感じる人は多いです。
理由は、最終的に JavaScript の関数として追いやすいからです。
- state は
useState - 更新は
setState - 副作用は
useEffect - UI は JSX
Vue は便利ですが、ref reactive computed watch など、リアクティブシステム側の概念が少し厚めです。
React はフックのルールを覚える必要はありますが、慣れると「この関数コンポーネントの中で何が起きるか」を追いやすいです。
まとめ
Vue の Composition API と React Hooks は、どちらも関数ベースでロジックを組み立てられます。
ただし、中心にある考え方は違います。
- Vue は reactivity 中心
- React は render と state 更新中心
-
computedとuseMemoは似て見えても役割の重さが違う -
watchとuseEffectも発想は同じではない
そのため、React のほうが分かりやすいと感じるなら、それは Hooks が「JavaScript の関数と state 更新」として追いやすいからです。
Vue のほうが自然に感じるなら、それは reactivity の抽象化がうまく効いているからです。