Skip to content

サーバーエラー統合

15.3.1. バックエンドエラーレスポンス形式

TQSバックエンド標準エラーレスポンスは以下の構造に従います。フロントエンドはこの形式に合わせてエラーを処理しなければなりません。

typescript
// src/types/api.ts
interface ApiErrorResponse {
  errorCode: string        // エラーコード(例:'VALIDATION_ERROR', 'CONFLICT')
  message: string          // ユーザー向けメッセージ
  fieldErrors?: {          // フィールドごとの検証エラー(任意)
    field: string
    message: string
  }[]
}
フィールド必須有無説明
errorCode必須エラー分類コード
message必須グローバルエラーメッセージ
fieldErrors任意フィールド単位の検証失敗リスト
  • fieldErrorsはフォーム送信時にサーバー側の検証が失敗した場合にのみ含まれます。
  • errorCodeはフロントエンドでエラー種別の分岐処理に使用します。

15.3.2. フィールドごとのエラーマッピング

サーバーから返されたfieldErrorsはフォームのerrors状態にマッピングします。

typescript
// src/utils/mapServerErrors.ts
import type { ApiErrorResponse } from '@/types/api'

export function mapFieldErrors(
  response: ApiErrorResponse
): Record<string, string> {
  const errors: Record<string, string> = {}

  if (response.fieldErrors) {
    for (const fieldError of response.fieldErrors) {
      errors[fieldError.field] = fieldError.message
    }
  }

  return errors
}

フォーム送信ハンドラーで以下のように適用します。

typescript
import { mapFieldErrors } from '@/utils/mapServerErrors'
import axios from 'axios'

async function handleSubmit() {
  isSubmitting.value = true
  errors.value = {}

  try {
    await createUser(form.value)
  } catch (e) {
    if (axios.isAxiosError(e) && e.response?.data) {
      const serverError = e.response.data as ApiErrorResponse
      errors.value = mapFieldErrors(serverError)
    }
  } finally {
    isSubmitting.value = false
  }
}
  • サーバーのfield値はフォームオブジェクトのキーと一致しなければなりません。
  • バックエンドとフロントエンド間のフィールド名規則を事前に合意します。

15.3.3. グローバルエラー処理

fieldErrorsにマッピングされないエラーはグローバルエラーとして処理します。トースト通知またはフォーム上部のバナーで表示します。

typescript
import { useToast } from '@/composables/useToast'

const { showToast } = useToast()

async function handleSubmit() {
  isSubmitting.value = true
  errors.value = {}

  try {
    await createUser(form.value)
  } catch (e) {
    if (axios.isAxiosError(e) && e.response?.data) {
      const serverError = e.response.data as ApiErrorResponse

      const fieldErrors = mapFieldErrors(serverError)
      if (Object.keys(fieldErrors).length > 0) {
        errors.value = fieldErrors
      } else {
        showToast({ type: 'error', message: serverError.message })
      }
    } else {
      showToast({ type: 'error', message: 'リクエスト処理中にエラーが発生しました。' })
    }
  } finally {
    isSubmitting.value = false
  }
}
エラー種別表示方式
フィールド検証エラーフィールド下部にインライン「既に使用されているメールアドレスです。」
ビジネスロジックエラートースト通知「1日の登録上限を超過しました。」
ネットワーク/サーバーエラートースト通知「リクエスト処理中にエラーが発生しました。」

15.3.4. エラーの初期化

ユーザーがフォームを修正すると、関連するエラーを自動的に初期化します。再送信時にはすべてのエラーを初期化します。

typescript
import { watch } from 'vue'

// 個別フィールド変更時に該当エラーを初期化
watch(
  () => form.value.email,
  () => {
    if (errors.value.email) {
      delete errors.value.email
    }
  }
)

// 汎用初期化 — フォーム全体を監視
watch(
  form,
  () => {
    errors.value = {}
  },
  { deep: true }
)
  • フィールド単位の初期化は特定フィールドのエラーのみを削除し、他のフィールドのエラーメッセージを維持します。
  • フォーム全体の監視はすべてのエラーを一括削除するため簡潔ですが、他のフィールドのエラーも消える点に注意します。
  • プロジェクト要件に応じて適切な戦略を選択します。

TIENIPIA QUALIFIED STANDARD