Search code examples
vue.jsaxiosvuexvuejs3vuex-modules

Vuex 4 Modules can't use global axios property


I have a Vue3 (without Typescript) app running Vuex 4.0.0.

I'm trying to set up a simple GET request in one of my store modules using axios, however I'm getting a Cannot read property of 'get' of undefined when I try to do it via an action called in one of my components, however if I call this.$axios from the component it works fine. For some reason, my modules can't use this.$axios, while elsewhere in the app I can.

I've declared $axios as a globalProperty in my main.js file.

// main.js

import { createApp } from "vue";
import App from "./App.vue";
import { router } from "./router";
import { store } from "./store";
import axios from "axios";

const app = createApp(App).use(store).use(router);
app.config.globalProperties.$axios = axios;

app.mount("#app");

And the store module looks like this (simplified for the purposes of this question):

// store/modules/example.js

const state = () => ({
  message: ""
});

const mutations = {
  getMessage(state, payload) {
    state.message = payload;
  }
};

const actions = {
  async setMessage(commit) {
    this.$axios.get("example.com/endpoint").then(response => {
      commit("setMessage", response.message);
    });
  }
};

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
};

The main store/index.js that's getting imported in main.js above looks like this:

// store/index.js

import "es6-promise";
import { createStore } from "vuex";

import example from "./modules/example";

export const store = createStore({ modules: { example } });

In the component, I have the following:

// MyComponent.vue

import { mapGetters, mapActions } from "vuex";

export default {
  computed: {
    ...mapGetters({
      message: "example/getMessage"
    })
  },
  methods: {
    ...mapActions({
      getMessage: "example/setMessage"
    })
  }
};

And a simple button with @click="getMessage". Clicking this button, however, returns Uncaught (in promise) TypeError: Cannot read property 'get' of undefined, but if I copy/paste the setMessage action into a component method, it works just fine.

Is there a way for me to expose this.$axios to the store files?


Solution

  • While this is not the ideal solution, as I would've preferred to have my $axios instance available globally with a single declaration in the mount file, it's probably the next best thing.

    I made a lib/axiosConfig.js file that exports an axios instance with some custom axios options, and I just import that one instance in every module that needs it.

    import axios from "axios";
    
    axios.defaults.baseURL= import.meta.env.DEV ? "http://localhost:8000": "example.com";
    axios.defaults.headers.common["Authorization"] = "Bearer " + localStorage.getItem("token");
    axios.defaults.headers.common["Content-Type"] = "application/json";
    // etc...
    
    export const $axios = axios.create();
    

    And in whatever module I need $axios in, I just import { $axios } from "./lib/axiosConfig. It's not perfect as I mentioned, since I do still have to import it in every module, but it's close enough as far as I can see, and has the added benefit of using the same axios config everywhere by just importing this file.