📖

NuxtJSでAxiosを使ってAPI共通処理を書いた(TypeScript)

4 min read

はじめに

今まで各VueファイルごとにAxios処理を書いていましたが、問題点が発生します。

  • コードの視認性の問題
  • API処理・エラー処理を統一化できない

上記の課題を解決したく、API関連のコードはリポジトリとしてまとめることにしました。
初心者ですので問題点などあれば、ご指摘よろしくお願いします。

インストール

"axios"ではなく、"@nuxt/axios"のインストールします。

$ npm i --save-dev @nuxtjs/axios

1.データの型定義ファイル

ResponseInterfaceはレスポンスデータの型です。
ArticleInterfaceは取得データ(オブジェクト型)の型であり、オリジナルで作成しました。
ArticleInterface配列で格納される前提です。

types/interface.d.ts
// 記事を返した時の型
export interface ResponseInterface {
    contents: Array<ArticleInterface>,
    limit: number,
    offset: number,
    totalCount: number,
}

2.処理共通化リポジトリ

大きな目的として「API処理・エラー処理を統一化」
このファイルでは「Axios/API通信に関するAPI共通処理クラスを作成」を行います。

repository/axiosrepository.ts
import { NuxtAxiosInstance } from '@nuxtjs/axios'
import { ResponseInterface } from "../types/interface"

export class AxiosRepository {

    // axiosの型定義
    private readonly axios: NuxtAxiosInstance

    // 初期化
    constructor(axios: NuxtAxiosInstance) {
        this.axios = axios
    }

    // レスポンスの取得
    // レスポンスの中身(私の場合はcontents)が存在しないと、エラー処理を行う仕様
    public async get(uri: string) {
        try {
            const response: ResponseInterface = await this.axios.$get(uri)
            return response.contents;
        } catch (e) {
            return Promise.reject(e);
        }
    }
}

3.API設定とInject定義

大きな目的として「共通化したAPI処理・エラー処理を呼び出せるようにする」
このファイルでは「共通化した関数をthis.$axiosRepositoryで呼び出せるinjectを定義」。

plugins/axios.ts
import { Plugin } from '@nuxt/types'
import { AxiosRepository } from '@/repository/axiosRepository'

export const repositoryPlugin: Plugin = (context, inject): void => {

    // api関連の情報(APIURLとKEY)を取得し設定
    const api = context.$axios.create({
        // https://nuxtjs.org/tutorials/moving-from-nuxtjs-dotenv-to-runtime-config/
        baseURL: context.$config.baseURL, // APIのURLを打ち込んでください
        headers: {
            "X-MICROCMS-API-KEY": context.$config.apiSecret, //APIのKEYを打ちこんください(APIの種類によって変動します)
        },
    })

    // VueインスタンスでInject化
    const axiosRepository = new AxiosRepository(api)
    inject('axiosRepository', axiosRepository)
};

export default repositoryPlugin

4.inject化した関数を型定義

現状、Typescriptを使用しているので、「this.$axiosRepositoryの型を定義」。
3と同じファイルの後ろに追記する。

plugins/axios.ts
// TypeScriptでの動作のために型定義
// Vueインスタンスから$axiosRepositoryを使用可能に
declare module 'vue/types/vue' {
    interface Vue {
        readonly $axiosRepository: AxiosRepository
    }
}

// this.$nuxt.contextから$axiosRepositoryを使用可能に
declare module '@nuxt/types' {
    interface NuxtAppOptions {
        readonly $axiosRepository: AxiosRepository
    }

    interface Context {
        readonly $axiosRepository: AxiosRepository
    }
}

5.nuxt設定ファイル

nuxt.config.js
export default {
   //・・・(省略)
   // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
   plugins: [{ src: '~/plugins/axios.ts' },],
   // Modules: https://go.nuxtjs.dev/config-modules
   modules: ['@nuxtjs/axios',],
   //・・・(省略)
}

6.Vueファイル

Vueファイルにて共通化したデータ取得処理をthis.$axiosRepository.getで呼び出すことができました。コード量が減って、視認性向上につながった気がします

index.vue
import { ArticleInterface } from "../types/interface";
import { Component, Vue } from "vue-property-decorator";

@Component
export default class Article extends Vue {
	const getArticles = async () => {
	      const res: ArticleInterface[] = await this.$axiosRepository.get(
		"/" // 呼び出したいクエリ文字列
	      );
	      this.articles = res;};
	getArticles();
}

問題点

$axiosRepositoryの型がまだanyの状態ですので、4で定義が正確に完了していないのか、vue-property-decoratorを適用しているので、そちらと関係があるのか・・・
修正できたら更新します。

参考

エラーを吐いた時に読んだドキュメント

https://typescript.nuxtjs.org/ja/cookbook/plugins
参考ってかめっちゃ真似た
https://qiita.com/itouuuuuuuuu/items/4132e3b7ddf2cbf02442
https://sagatto.com/20201229_nuxt_axios_ts_repository

Discussion

ログインするとコメントできます