【Vue.js】Composable関数でロジックを共通化する方法|useFetch・useFormの実装例

【Vue.js】Composable関数でロジックを共通化する方法|useFetch・useFormの実装例 Vue.js

Vue 3 の Composition API では、処理の共通化や再利用性を高める手段として Composable関数 が広く使われています。ロジックを切り出すことで、コンポーネントの可読性を高め、メンテナンス性を向上させることができます。

この記事では、代表的な共通ロジックである「API取得処理」と「フォームバリデーション処理」を対象に、useFetchuseFormという2つのComposable関数を実装し、活用方法を解説します。

Composable関数とは

Composable関数とは、Vue 3 の Composition API を使って定義する「状態とロジックの再利用可能なユニット」です。通常、refreactivewatchcomputed などを内部で利用し、必要なデータや関数を返します。

命名には use〜 というプレフィックスを用いるのが一般的です(例:useUseruseFetchなど)。

useFetchの実装例|API取得ロジックの共通化


// composables/useFetch.js
import { ref } from 'vue';

export function useFetch(url) {
  const data = ref(null);
  const error = ref(null);
  const loading = ref(false);

  const fetchData = async () => {
    loading.value = true;
    error.value = null;
    try {
      const res = await fetch(url);
      if (!res.ok) throw new Error('Fetch failed');
      data.value = await res.json();
    } catch (err) {
      error.value = err.message;
    } finally {
      loading.value = false;
    }
  };

  return {
    data,
    error,
    loading,
    fetchData
  };
}

このuseFetchを使えば、APIからのデータ取得をシンプルに扱うことができます。

使用例


<script setup>
import { onMounted } from 'vue';
import { useFetch } from './composables/useFetch';

const { data, error, loading, fetchData } = useFetch('https://api.example.com/users');

onMounted(() => {
  fetchData();
});
</script>

<template>
  <div v-if="loading">読み込み中...</div>
  <div v-else-if="error">エラー: {{ error }}</div>
  <ul v-else>
    <li v-for="user in data" :key="user.id">{{ user.name }}</li>
  </ul>
</template>

useFormの実装例|フォームバリデーションの共通化


// composables/useForm.js
import { reactive, computed } from 'vue';

export function useForm(initialState = {}) {
  const form = reactive({ ...initialState });
  const errors = reactive({});

  const validate = () => {
    errors.name = !form.name ? '名前は必須です' : '';
    errors.email = !form.email ? 'メールアドレスは必須です' : '';
    return Object.values(errors).every(e => !e);
  };

  const isValid = computed(() => Object.values(errors).every(e => !e));

  return {
    form,
    errors,
    validate,
    isValid
  };
}

使用例


<script setup>
import { useForm } from './composables/useForm';

const { form, errors, validate, isValid } = useForm({
  name: '',
  email: ''
});

const submit = () => {
  if (validate()) {
    alert('送信成功');
  }
};
</script>

<template>
  <form @submit.prevent="submit">
    <div>
      <input v-model="form.name" placeholder="名前">
      <p v-if="errors.name">{{ errors.name }}</p>
    </div>
    <div>
      <input v-model="form.email" placeholder="メールアドレス">
      <p v-if="errors.email">{{ errors.email }}</p>
    </div>
    <button :disabled="!isValid">送信</button>
  </form>
</template>

まとめ

Composable関数は、Vueコンポーネントのロジックを整理・共通化する強力な手段です。useFetchでAPI呼び出しの共通処理を、useFormでバリデーション処理を切り出すことで、コンポーネントをよりシンプルに保つことができます。

アプリケーションの拡張性やチーム開発での可読性を高めるためにも、プロジェクト内で積極的にComposable関数を導入してみてください。