(vue) Uncaught InternalError: too much recursion: failed to use axios - vue.js

I met a weird problem, when I set up main.js and run the server, it shows me this error
and here is my code in main.js,
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus';
import axios from 'axios'
import 'element-plus/lib/theme-chalk/index.css';
axios.defaults.baseURL = 'http://localhost:8000'
const app = createApp(App)
app.use(store)
app.use(router)
app.use(ElementPlus)
console.log('1111')
app.use(axios)
console.log('aaa')
app.mount('#app')
I set a console.log to track the error, the '1111' shows but 'aaa' never shows, so I can only know the error occurs in the line app.use(axios), that's so confusing, did anyone ever met this problem? How to solve it?

Here you have 2 options:
If you're using Vue3, import it in your Vue, like you did, but as written in this awnser, i think you should do something more like that:
import { createApp } from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
app.use(VueAxios, axios) // 👈
app.mount('#app')
You wanna use only axios and don't get bothered by it, then you don't have to use VueAxios or make something like app.use(axios) in your main.js, and then make a httpRequestsService file which will handle all the axios part.
For example, here is mine:
import axios from "axios";
axios.defaults.baseURL = process.env.API_BASE_URL
axios.interceptors.response.use(res => res, err => {
// some code if you wanna handle specific errors
throw err;
}
);
const getHeader = (method, endpoint, header, body) => {
const publicEndpoints = [
{
method: 'POST',
endpoint: '/auth/local'
}
]
const publicEndpoint = publicEndpoints.find(e => e.method === method && e.endpoint === endpoint)
if (!publicEndpoint) {
header.Authorization = localStorage.getItem("jwt")
}
return body ? { headers: header, data: body } : { headers: header }
}
export default {
get(endpoint, header = {}) {
return axios.get(endpoint, getHeader('GET', endpoint, header))
},
post(endpoint, body = {}, header = {}) {
console.log(body)
return axios.post(endpoint, body, getHeader('POST', endpoint, header))
},
put(endpoint, body = {}, header = {}) {
return axios.put(endpoint, body, getHeader('PUT', endpoint, header))
},
delete(endpoint, body = {}, header = {}) {
return axios.delete(endpoint, getHeader('DELETE', endpoint, header, body))
},
}

Related

Vue3 Composition API Apollo Client userMutation() in watch function

I am using Vue3 with the composition API and Apollo client.
I use an useQuery() function to query some data. With it I use a watcher like watch(result, (newVal) => {})
What I want to do is, using the useMutation() inside this watcher. But it does not work at all.
This is the error message I get:
Uncaught (in promise) Error: Apollo client with id default not found. Use provideApolloClient() if you are outside of a component setup.
at resolveClient (useApolloClient.ts:68:13)
at mutate (useMutation.ts:78:20)
at VerifyEmailView.vue:31:9
at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
at job (runtime-core.esm-bundler.js:1776:17)
at callWithErrorHandling (runtime-core.esm-bundler.js:155:36)
at flushJobs (runtime-core.esm-bundler.js:388:17)
This is the code I use
import { useRouter } from 'vue-router'
import { useRoute } from 'vue-router'
import { useMutation, useQuery } from '#vue/apollo-composable'
import { useSessionStore } from '#/stores/SessionStore'
import UPDATE_NFCUSER_EMAIL_VERIFICATION_CODE from '#/graphql/UpdateNfcUserEmailVeriifcationCode.mutation.gql'
import GET_NFCUSER_ID_BY_EMAIL_VERIFICATION_CODE from '#/graphql/GetNfcUserIdByEmailVerificationCode.query.gql'
import { watch, ref } from 'vue'
const sessionStore = useSessionStore()
const router = useRouter()
const route = useRoute()
const route_verification_code = route.params.verification_code
const code_not_verified = ref(false)
const { result } = useQuery(GET_NFCUSER_ID_BY_EMAIL_VERIFICATION_CODE, {
verification_code: route_verification_code,
})
watch(result, (newVal) => {
if (newVal?.getNfcUserIdByEmailVerificationCode?.status === 200) {
const nfc_user_id = newVal?.getNfcUserIdByEmailVerificationCode?.nfc_user_id
if (nfc_user_id) {
console.log('Verification Code is valid')
sessionStore.setCurrentUserVerified(true)
sessionStore.setCurrentNfcUserId(nfc_user_id)
const { mutate } = useMutation(UPDATE_NFCUSER_EMAIL_VERIFICATION_CODE)
mutate({
nfcUserId: nfc_user_id,
})
} else {
console.log('Code is not correct')
code_not_verified.value = true
}
} else {
console.log('Code is not correct')
code_not_verified.value = true
}
})
Looking at the error it seems you would want to set the mutation variable outside of the watch() the same way you're using the query;
const { mutate: updateNfcUserEmailVerificationCode } = useMutation(UPDATE_NFCUSER_EMAIL_VERIFICATION_CODE);
// watch function
updateNfcUserEmailVerificationCode({ nfcUserId: nfc_user_id });
If you did want to use it in the watch() function it looks like you'll have to use the Apollo client directly: https://v4.apollo.vuejs.org/guide-option/mutations.html
// watch function
this.$apollo.mutate({
mutation: UPDATE_NFCUSER_EMAIL_VERIFICATION_CODE,
variables: { nfcUserId: nfc_user_id },
});

how to get access to vuex inside other js files like plugins in nuxt

i have a problem. i wanna get access to one of my getters inside my vee-validate.js file.
how can i do that?
in my pages and components, (in <script>...</script> part, outside export default{...}) i used this function:
component.vue
<script>
let lang;
function getLang({store}) {
lang = store.state.lang
}
export default{
...
}
but it is not working!
i'm trying to access my custom lang file (for translation purpose) that is stored in lang state in my vuex, and use it in vee-validate.js file for custom message.
i tried to import store but not working.
veevalidate.js:
import Vue from 'vue'
import { required } from 'vee-validate/dist/rules'
import { extend, ValidationObserver, ValidationProvider, setInteractionMode } from 'vee-validate'
import {store} from '../store'
let langFile = store
setInteractionMode('eager')
extend('required', {
...required,
message: ''
})
Vue.component('ValidationProvider', ValidationProvider);
Vue.component("ValidationObserver", ValidationObserver);
UPDATED: My store index.js
import langfile from '../static/lang'
export const state = () => ({
lang: null,
dir: null,
})
export const getters = {
//----------------- Language and Direction
lang(state){
return state.lang
},
dir(state){
return state.dir
},
}
export const mutations = {
SET_LANGUAGE(state, lang){
state.lang = lang
},
SET_DIRECTION(state, dir){
state.dir = dir
},
}
export const actions = {
async nuxtServerInit({dispatch, commit}) {
// ------------- Read Language File
let baseLang = process.env.SITE_LANGUAGE;
let siteLang = langfile[baseLang];
let siteDir = langfile[baseLang]['dir'];
commit('SET_LANGUAGE', siteLang);
commit('SET_DIRECTION', siteDir);
},
}

Quasar Axios request wrong URL (Double URL)

The Error Image
when i send request via axios with url axios concatenate url of api
with the url of the quasar dev server how can i neglect this
concatenation and send the API url only there is any configuration for
baseUrl of axios with quasar ?
src/boot
import axios from 'axios'
export default async ({ Vue }) => {
axios.defaults.baseURL = 'http//:localhost:3000/'
Vue.prototype.$axios = axios
}
the componennt :
this.$axios({
url : 'backend/spots/all',
}).then(response=>{
this.allSlots = response.data
})
According Quasar documentation you can try it as below:
// src/boot/axios.js
const axiosInstance = axios.create({
baseURL: 'http//:localhost:3000'
})
export default async ({ Vue }) => {
Vue.prototype.$axios = axiosInstance
...
}
export { axiosInstance }
to use in some vue | js file:
import { axiosInstance } from 'src/boot/axios'
axiosInstance.get('/some-endpoint')
I am not sure, but can you try to change axios.defaults.baseURL = 'http//:localhost:3000/' to axios.defaults.baseURL = 'http://localhost:3000/' (change colon place) ?
For anyone reading this.
According to quasar axios boot file documentation you can try a more cleaner way...
import Vue from 'vue'
import axios from 'axios'
// we add it to Vue prototype
// so we can reference it in Vue files as this.$axios
// without the need to import axios or use vue-axios
Vue.prototype.$axios = axios
// can also create an axios instance specifically for the backend API
const api = axios.create({ baseURL: 'https://api.example.com' })
Vue.prototype.$api = api
export { axios, api }
I was having the same issue, in quasar.config.js under build I had
env: ctx.dev ? { // so on dev we'll have
API: JSON.stringify('https://my.staging.api/v1/')
} : { // and on build (production):
API: JSON.stringify('https://my.api/v1/')
},
removing JSON.stringify solved the issue
env: ctx.dev ? { // so on dev we'll have
API: 'https://my.staging.api/v1/'
} : { // and on build (production):
API: 'https://my.api/v1/'
},

How to use axios in Vue2 project created with vue-cli3

I created a new vue project using the command vue create axe using vue-cli-3.0.016beta. Then installed axios using npm install axios --save. In the main.js file I imported axios as shown below.
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
Vue.config.productionTip = false
Vue.use(axios)
new Vue({
render: h => h(App)
}).$mount('#app')
There is not a bit of code change other than this. Still I get an error like the following:
Unhandled promise rejection
TypeError
​
columnNumber: 7
​
fileName: "http://localhost:8080/app.js line 1065 > eval"
​
lineNumber: 57
​
message: "parsed is undefined"
​
stack: "isURLSameOrigin#webpack-internal:///./node_modules/axios/lib/helpers/isURLSameOrigin.js:57:7\ndispatchXhrRequest#webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:109:50\nPromise#webpack-internal:///./node_modules/core-js/modules/es6.promise.js:177:7\nxhrAdapter#webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:12:10\ndispatchRequest#webpack-internal:///./node_modules/axios/lib/core/dispatchRequest.js:59:10\nrun#webpack-internal:///./node_modules/core-js/modules/es6.promise.js:75:22\nnotify/<#webpack-internal:///./node_modules/core-js/modules/es6.promise.js:92:30\nflush#webpack-internal:///./node_modules/core-js/modules/_microtask.js:18:9\n"
​
__proto__: Object { stack: "", … }
I want to axios globally to use interceptors, hence calling it here in main.js. But if I use it in a view-page there is no error!
is this a bug or I'm doing it wrong? Kindly help me to fix this and use axios globally.
Thanks
so the error I see is here
Vue.use(axios)
Vue.use expects a vue installable plugin.
You could have a look at vue-axios
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
but I would highly discourage it.
It's best to create your own ApiHandler.js file that handles all the remote stuff separately, and you can easily call from anywhere including vue components and vuex.
here is the beginning of my class
<script>
import axios from 'axios';
class ApiHandler{
constructor(apiUrl) {
this.axios = axios;
this.apiUrl = apiUrl || ''; // this line allow passing a custom endpoint for testing
this.config = {
headers: { 'Cache-Control': 'no-cache' }, // can setup to prevent all caching
baseURL: this.apiUrl,
};
}
/**
* #param {Object} payload
* #param {String} payload.username
* #param {String} payload.password
*/
login({ username, password }) {
return new Promise((resolve, reject) => {
this.axios.post('/api/login', { username: username.toLowerCase(), password }, this.config)
.then((response) => {
if (response.code === 200 && response.body && response.body.token) {
resolve(response.body.token);
} else {
reject('Bad Login');
}
})
.catch((err) => {
reject('internal error');
});
});
}
}
</script>
you can then call this from anywhere by...
<script>
import ApiHandler from '../lib/ApiHandler';
const apiRequest = new ApiRequest();
// and then anywhere in the script
let payload = {
username:'someuser',
password:'somepassword',
};
apiRequest.login(payload)
.then(()=>{
// yay - I'm logged in
})
.catch(err => {
// oh oh, display error
})
</script>
this gives you much more flexibility and allows you to separate the remote actions and allows doing first-leg response handling separate of your component, which allows more re-usability.
instead of
Vue.use(axios);
you should
Vue.prototype.$axios = axios;
then you can use it globally
login() {
this.$axios.post('<host>/api/login', data)
.then((res) => { // dosomething })
.catch((err) => { // dosomething });
}
if you want to add globally interceptors with axios, you can
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
// and
Vue.prototype.$axios = axios;

After Nuxt build api returns 404

I'm having this weird issue and I seriously need your help. In development my code works perfectly fine but after doing nuxt build and all the apis are returning 404 error. Please help
When I'm building the api and running it, it works. In development api and nuxt both works but building nuxt and the api, doesn't work.
Following are my configuration
Server configuration
import convert from 'koa-convert';
import cors from 'kcors';
import bodyParser from 'koa-body';
import session from 'koa-session';
import helmet from 'koa-helmet';
import config from 'config';
import serve from 'koa-static';
import mount from 'koa-mount';
import { cModules, cMiddleware } from '../app';
import { catchErr, statusMessage } from './errorConfig';
import nuxtConfig from './nuxtConfig';
function baseConfig(app, io) {
app.keys = config.get('secret');
app.proxy = true;
app.use(mount('/static', serve(config.get('paths.static'))));
app.use(convert.compose(
catchErr,
cors({
credentials: true,
origin: true
}),
bodyParser({
multipart: true,
formLimit: '200mb'
}),
session({
maxAge: 21600000
}, app),
helmet(),
statusMessage
));
cModules(app, io);
app.use(cMiddleware());
if (config.get('nuxtBuild')) {
nuxtConfig(app);
}
}
export default baseConfig;
And my Nuxt
import { Nuxt, Builder } from 'nuxt';
import koaConnect from 'koa-connect';
import isDev from 'isdev';
import config from '../../../nuxt.config';
async function nuxtConfig(app) {
const nuxt = new Nuxt(config);
if (isDev) {
await new Builder(nuxt).build();
}
const nuxtRender = koaConnect(nuxt.render);
app.use(async (ctx, next) => {
await next();
ctx.status = 200;
ctx.req.session = ctx.session;
await nuxtRender(ctx);
});
}
export default nuxtConfig;