How to use vue-axios in Vue3 Composition API? - express

I'm using express with NodeJS for running the APIs
For Authentication I'm using the below package
const session = require('client-sessions');
app.use(session({
cookieName: 'session',
secret: process.env.COOKIE_SECRET,
duration: 30 * 60 * 1000 * 30,
activeDuration: 60 * 60 * 1000 * 30
}));
I'm using express
I have imported axios and VueAxios in my main.js file with the below code:
import { createApp } from 'vue'
import App from './App.vue'
import './assets/style.css'
import router from './router'
import axios from 'axios';
import VueAxios from 'vue-axios';
const app = createApp(App)
app.use(VueAxios, axios, router)
app.provide('axios', axios)
app.provide('VueAxios', VueAxios)
app.mount('#app')
Here is the code in my Component Javascript Block
import { onBeforeMount, onMounted, ref, inject } from "vue";
setup() {
const axios = inject('axios');
const VueAxios = inject('VueAxios');
onMounted(async ()=> {
VueAxios.axios.get(...... // I get this error - Cannot read property 'get' of undefined
VueAxios.get(...... // I get this error - VueAxios.get is not a function
axios.get(...... // this works, but how do I use VueAxios for passing session payload?
})
}

Adding the below line of code after app.provide('VueAxios', VueAxios) made it work
axios.defaults.withCredentials = true;

Related

How to use Axios globally using composition API

I'm having trouble getting Axios to work using the composition API. The following is what I've done, but I'm unsure how to access Axios within setup(). I'm aware that the "this" keyword is no longer available in the composition API.
Created an axio.js file in /plugins:
import axios from 'axios'
export default {
install: (app, options) => {
app.config.globalProperties.axios = axios.create({
baseURL: options.baseUrl,
withCredentials: true,
headers: {
Authorization: options.token ? `Bearer ${options.token}` : '',
}
})
}
}
Added it to plugins/index.js
import { loadFonts } from './webfontloader'
import vuetify from './vuetify'
import pinia from '../store'
import router from '../router'
import axios from './axios'
export function registerPlugins (app) {
loadFonts()
app
.use(vuetify)
.use(pinia)
.use(router)
.use(axios, { baseUrl: import.meta.env.VITE_AXIOS_BASE_URL })
}
Then the main.js file registers all plugins:
import App from './App.vue'
// Composables
import { createApp } from 'vue'
// Plugins
import { registerPlugins } from '#/plugins'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')

Error: vue-composition-api No vue dependency found

I am having an issue with vue-composition-api.
I have included it in my main.ts as an include like this:
import "./registerServiceWorker";
import Vue from "vue";
import "./_core/plugins/composition-api";
import "./_core/plugins/global";
import "./_core/plugins/cloudinary";
import "./_core/plugins/gtm";
import { provide } from "#vue/composition-api";
import { ApolloClients } from "#vue/apollo-composable";
import vuetify from "./_core/plugins/veutify";
import contentfulClient from "./_core/plugins/vue-apollo-contentful";
import apiClient from "./_core/plugins/vue-apollo-api";
import VAnimateCss from "v-animate-css";
import App from "./app.component.vue";
import router from "./router";
import store from "./store";
Vue.config.productionTip = false;
import Meta from "vue-meta";
Vue.filter("formatPrice", function (value: string | number) {
if (typeof value !== "number") {
return value;
}
const formatter = new Intl.NumberFormat("en-GB", {
style: "currency",
currency: "GBP",
minimumFractionDigits: 2,
});
return formatter.format(value);
});
import "./scss/_core.scss";
Vue.filter("time", function (value) {
const date = new Date(value);
const options = {
timeZoneName: "short",
hour: "2-digit",
minute: "2-digit",
};
// eslint-disable-next-line
return date.toLocaleTimeString("en-GB", <any>options);
});
Vue.use(Meta, {
keyName: "head",
});
Vue.use(VAnimateCss);
new Vue({
router,
store,
vuetify,
setup() {
provide(ApolloClients, {
default: apiClient,
apiClient,
contentfulClient,
});
},
render: (h) => h(App),
}).$mount("#app");
compoistion-api.ts looks like this:
import Vue from "vue";
import vueCompositionApi from "#vue/composition-api";
Vue.use(vueCompositionApi);
This compiles, but in my application I see this error:
When digging deeper, I can see that it's complainling about my graph-query.ts script, which is imported in my get-metadata.ts script and in-turn is imported in app.component.ts.
I thought the main.ts file is imported first, so it should use composition-api before the app is mounted? Am I missing something here?
Let me know if you need more information
For anyone stumbling upon this: it might be because the composition API plugin is not initialized before using the API.
From a related github issue:
I had the same issue, it's because you are declaring any reactive elements (ref() / reactive()) before the plugin is installed in your Vue instance.
You can fixing by calling Vue.use(VueCompositionAPI) before importing any of your components/store

Vue.use() is throwing "Cannot read property 'use' of undefined"

Attempt 1
main.js
import { createApp } from 'vue'
import { store } from './store/store'
import App from './App.vue'
Vue.config.productionTip = false
const app = createApp(App)
app.use(store)
app.mount('#app')
store.js
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
patients: []
}
});
Attempt 1 Error
Uncaught TypeError: Cannot read property 'use' of undefined
at eval (store.js?07a4:4)
at Module../src/store/store.js (app.js:1342)
Attempt 2
main.js
import { createApp } from 'vue'
import { store } from './store/store'
import App from './App.vue'
Vue.config.productionTip = false
const app = createApp(App)
app.use(store)
app.mount('#app')
store.js
import Vuex from 'vuex'
import Vue from 'vue'
export const store = new Vuex.Store({
state: {
patients: []
}
});
Attempt 2 Error
vuex.esm.js?94ea:135 Uncaught Error: [vuex] must call Vue.use(Vuex) before creating a store instance.
at assert (vuex.esm.js?94ea:135)
at new Store (vuex.esm.js?94ea:380)
at eval (store.js?07a4:6)
I created a Vue application using Vue CLI. I am trying to implement Vuex. I have followed numerous tutorials (usually set up 2 different ways). When using a debugger, I was able to stop before it read "Vue.use(Vuex)". Logging Vue at this point returns undefined. I believe my imports are correct but do not know if I am missing something crucial. Any help is much appreciated.
EDIT: The only difference between Attempt 1 and 2 is I removed "Vue.use(Vuex)" on Attempt 2.
You're using vuex 3 syntax with Vue 3 which is compatible with vuex 4 that has the following syntax :
store.js
import { createStore } from 'vuex'
// Create a new store instance.
const store = createStore({
state: {
patients: []
}
})
export default store;
then use the exported store in the main.js :
import { createApp } from 'vue'
import store from './store/store'
import App from './App.vue'
Vue.config.productionTip = false
const app = createApp(App)
app.use(store)
app.mount('#app')
Vuex 4 docs
Vue.js 3 docs
I was able to get this working by uninstalling my VueX (3.6)
npm uninstall vuex
and installing the VueX (4.0 alpha)
npm i vuex#4.0.0-alpha.1
The reason for this error was because I was using 2 different syntax methods from different versions.
Thanks for everyone's help!
main.js
import { createApp } from 'vue'
import { store } from './store/store'
import App from './App.vue'
const app = createApp(App)
app.use(store)
app.mount('#app')
store.js
import { createStore } from 'vuex'
// Create a new store instance.
const store = createStore({
state () {
return {
patients: []
}
}
})
export default store;

How to get access to the Root inside the setup method of Vue 3 component?

I have an Vue App.
I use vuex.
I created my app like this:
import { createApp } from "vue";
import axios from "axios";
import App from "./App.vue";
import router from "./router";
import store from "./store/index";
axios.defaults.baseURL = "https://localhost:44349";
const app = createApp(App)
.use(router)
.use(store)
.mount("#app");
Than i one of my component i am trying to access context.root.$store in the setup() method
, but context.root is undefined.
<script>
import {ref, computed } from "vue";
export default {
name: "ClientList",
setup(props, context) {
const clients = ref([]);
console.log(context);
const clientOrdersLenght = computed(() => {
return clients.value.length;
});
return { clients, clientOrdersLenght }
},
};
</script>
My idea is get acces to my store via context.root. I watched videos and examples with this. but they refer to Vue 2 using 'vue/composition-api' as import.
What i am missing?
You might be able to include and access the store directly
store.dispatch('myModule/myModuleAction')
store.myModule.state.blabla
import {ref, computed } from "vue";
import store from './store/index'; // include store
export default {
name: "ClientList",
setup(props) {
const clients = ref([]);
const clientOrdersLength = computed(() => {
store.dispatch('myAction'); // call dispatch
store.state.myItem // or access store's state
return clients.value.length;
});
return { clients, clientOrdersLength }
},
};
I found an easy way to access my store with getStore() from vuex. That's cool.
But for other reason in the feature, me or somebody else will need to access the $root (vue instance) of the app. So may be now the correct question is how to get the $root (vue instance) of the app in a child component?

Import Axios Method Globally in Vuejs

this is my ~/plugins/axios.js file:
import axios from 'axios'
let api = axios.create({
baseURL: 'http://localhost:8000/api/v1/'
})
export default api
When I want to use axios in every components, I must have write this line:
import api from '~/plugins/axios
How can i config it globally, just write $api instead?
You can create a plugin and use it like this in your main.js file (if you're using something like vue-cli)
import axios from 'axios'
Vue.use({
install (Vue) {
Vue.prototype.$api = axios.create({
baseURL: 'http://localhost:8000/api/'
})
}
})
new Vue({
// your app here
})
Now, you can do this.$api.get(...) on every component method
Read more about Vue plugins here: https://v2.vuejs.org/v2/guide/plugins.html
Provide/Inject could be an option as well: https://v2.vuejs.org/v2/api/#provide-inject
There is a window object available to you in the browser. You can actively leverage that based on your requirements.
In the main.js file
import axiosApi from 'axios';
const axios = axiosApi.create({
baseURL:`your_base_url`,
headers:{ header:value }
});
//Use the window object to make it available globally.
window.axios = axios;
Now in your component.vue
methods:{
someMethod(){
axios.get('/endpoint').then(res => {}).catch(err => {});
}
}
This is basically how I use axios globally in my projects. Also, this is also how Laravel uses it.
Keeping this in main.js works perfectly fine for me in Vue 3.
import { createApp } from 'vue';
import App from './App.vue';
import axios from "axios";
const app = createApp(App);
const instance = axios.create({
baseURL: 'https://example.com/',
});
app.config.globalProperties.axios=instance
app.mount('#app');
and to use it in any component,
this.axios.post('/helloworld', {
name: this.name,
age: this.age
})