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?
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.