くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Nuxt/TS】vuex-module-decorators+nuxt-client-initで、nuxtClientInit内で@nuxt/axiosが取得できないときの対処法

TypeScriptでNuxtしたくて、vuex-module-decoratorsnuxt-client-initを使ったら、
nuxtClientInit内で$axiosがnullだったときの備忘録。

Nuxt TypeScriptのストアのガイドを見ているけど、
プラグインのほうが後に呼ばれるので、自分で初期化しないといけないっぽい。

ソースはこんな感じ。

そもそもvuex-module-decoratorsのストア内で、
$axiosなどを使う時は少しめんどくさい。。

~/src/utils/api.ts

// ~/src/utils/api.ts
// axiosを保持しておく関数
import { NuxtAxiosInstance } from "@nuxtjs/axios";

let $axios: NuxtAxiosInstance;

export function initializeAxios(axiosInstance: NuxtAxiosInstance) {
  console.info("**** initializeAxios");
  $axios = axiosInstance;
}

export { $axios };

~/plugins/axios-accessor.ts

// ~/plugins/axios-accessor.ts
// Nuxt初期化時にinitializeAxios()を使って、
// $axiosを保持しておくプラグイン
import { Plugin } from "@nuxt/types";
import { initializeAxios } from "~/src/utils/api";

const accessor: Plugin = ({ $axios }) => {
  initializeAxios($axios);
};

export default accessor;

nuxt.config.ts

// nuxt.config.ts
import { Configuration } from "@nuxt/types";

const config: Configuration = {
  mode: "spa",
  // 略
  
  // 作成したプラグインを追加
  plugins: ["~/plugins/axios-accessor.ts"],
  // nuxt-client-init-moduleを最初に設定
  modules: [
    "nuxt-client-init-module",
    // 略
  ],
  // 略
};

export default config;

ここまでが、ストア内で$axiosを使うための設定。
これで、ストアだけじゃなくどこからでも、以下で$axiosにアクセスできる。

import { $axios } from "~/src/utils/api";

~/store/index.ts

ここからが本題。

import { $axios } from "~/src/utils/api";が、
nuxtClientInit内でも使えるかと思ったら、だめだった。。

importした$axiosを見てみるとnullであり、初期化後の保持がされていないよう。
呼び出し順序の関係上、axiosAccessorを呼び出す必要がある。

// ~/store/index.ts
import { ActionTree, Store } from "vuex";
import { initialiseStores, userStore } from "~/store/store-accessor";
import axiosAccessor from "~/plugins/axios-accessor";

export const state = () => ({});
export type RootState = ReturnType<typeof state>;

const initializer = (store: Store<any>) => initialiseStores(store);
export const plugins = [initializer];

export const actions: ActionTree<any, any> = {
  // nuxtClientInitの処理
  async nuxtClientInit(context: any, app: any) {
    // $axiosの初期化を自分でする
    await axiosAccessor(app, v => {});

    // app.$axiosを使ってなんかする
  }
};

export * from "~/store/store-accessor";

これでOK。nuxtClientInitではapp.$axiosを使い、
他のクラスやストアモジュール内では、
import { $axios } from "~/src/utils/api";でアクセスできようになる。

以上!!

参考サイト - Examples of how to use the modules in a Vue component · Issue #80 · championswimmer/vuex-module-decorators - nuxt + typescript + vuex + axios に手を焼いたので共有 - Qiita - potato4d/nuxt-client-init-module: Provide client version of nuxtServerInit