概要
ロジックの再利用とは「共通関数にすること」ではない。
それは**“横断的に使われる処理を、意味と責務で切り出し、依存から切り離して拡張可能にする戦略的設計”**である。
Vueの Composables、Reactの Custom Hooks は、ただの「便利関数」ではなく、UI層とロジック層を分離し、アプリを構造的に再利用可能にするための設計装置である。
1. Composables / Hooks の定義と責務
// React
function useUserLoader(id) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${id}`).then(res => res.json()).then(setUser);
}, [id]);
return user;
}
// Vue
export function useUserLoader(id) {
const user = ref(null);
onMounted(async () => {
user.value = await api.fetchUser(id);
});
return { user };
}
- ✅ 外部から 値や関数を受け取り、副作用や状態を内部で完結
- ✅ UIに依存せず、意味単位で再利用可能
2. 「再利用される」ではなく「再利用可能である」が設計基準
❌ UIと密結合 → 他のコンポーネントで使えない
✅ ロジックを抽象化 → UIに依存しないComposableに
export function useToggle(defaultValue = false) {
const state = ref(defaultValue);
const toggle = () => (state.value = !state.value);
return { state, toggle };
}
3. 横断的関心事(Cross-cutting Concerns)の分離設計
- ローディング制御 → useLoading
- エラーハンドリング → useError
- APIフェッチ汎用化 → useFetch
- モーダル開閉 → useModal
- ✅ どの画面にも関係する処理は 横断ユースケースとして切り出す
4. UIとの境界を明確に保つ
❌ useXxx の中で DOM に直接アクセス
✅ UIイベントは親で受け取り、Composableには状態とロジックのみを閉じ込める
- ✅ Composables / Hooks は ロジックレイヤーに留める
- ✅ 表示・入力との直接操作は UI側に残す
5. Composables / Hooks の構成粒度と依存戦略
- useUser → 小さすぎて曖昧
- useFetchUser → 責務明確
- usePaginatedUserList → 意味単位で再利用可能
- ✅ データ・副作用・UI操作が混ざらないよう設計
- ✅ API依存・状態依存は引数注入にすると柔軟性が高まる
6. テスト可能な構造を保つ(Pure & Injected)
export function useUserFetcher(apiClient) {
const user = ref(null);
const fetch = async (id) => {
user.value = await apiClient.fetchUser(id);
};
return { user, fetch };
}
- ✅ 外部依存(API)を注入可能に → テスト時はモックに置き換え
- ✅ Composables / Hooks を プレーンなロジックレイヤーとして扱う
設計判断フロー
① この処理は他でも使えるか? → 目的単位でComposableに切り出す
② UIに依存していないか? → DOM / props に密結合していないか確認
③ 状態管理・副作用・UI操作が1ファイルに混在していないか?
④ 外部依存を内部に閉じ込めていないか? → 引数注入で柔軟化
⑤ Composable内の構造がテスト可能か? → 外部に出す責務を定義
よくあるミスと対策
❌ Composable の中でUI状態まで握ってしまう
→ ✅ 状態はロジックに限定し、UI制御は外に出す
❌ 毎回似た処理を書いてコピペ地獄に
→ ✅ useFetch系や useToggle系など汎用Composableを整備
❌ Composableが肥大化して読めなくなる
→ ✅ 1関数1責務 + 機能単位でファイル分離
結語
ロジックの再利用とは「まとめること」ではない。
それは**“意味で分け、責務で切り出し、構造として再利用可能にする設計行為”**である。
- 状態・副作用をComposableに閉じ込め
- UIとロジックを明確に分離し
- 外部依存を注入構造で制御し
- 横断的なロジックを柔軟に再利用する
JavaScriptにおけるロジック再利用戦略とは、
“破綻せず拡張可能な構造を作り出す、責任と柔軟性のデザイン”である。