Vue - Axios Error : Cannot read properties of undefined (reading 'get') - vue.js

I'm making a Crud using Vue and axios.
My "create component" is working fine, but I have a problem with my "edit component".
The two components are the same except that the edit one have a parameter on the URL ("myweb.com?id=3") and on mounted cycle I make an axios call to retrieve the register data.
mounted() {
this.$http.get("/api/getOrder?id=" + this.order).then((response) => {
this.complements = response.data
}); ...
I get this error "::: TypeError: this.$http is undefined" that break my code.
In my axios.js I have my prototype defined which is working fine on the rest of components:
Vue.prototype.$http = axiosIns
The weird thing is that this error only appear on production (not on local) and is intermittent (sometimes it works correctly, sometimes fails ... no pattern found)
EDIT ::
I realize that if I remove the axios call from mounted and put it on a button-method it works perfectly
Any help will be appreciate

Related

reading vue.js variables from the js console

Let's say I had this:
var app = new Vue({
el: '#app',
data: {
message: Math.random()
}
})
And let's say that I wanted to see what value data.message had been assigned in the JS console. How would I do this?
Superficially it seems like doing console.log(app.data.message) would do the trick but when I try to do that I get a Uncaught TypeError: Cannot read properties of undefined (reading 'message') error. In fact, it turns out that app.data is undefined.
So how can I do this?
Here's a JS fiddle with this code:
https://jsfiddle.net/dfzun3by/4/
That code is based off of https://v2.vuejs.org/v2/guide/?redirect=true#Declarative-Rendering
As a corollary to this question... in some production code that I'm now responsible for we don't have that - we have something more akin to this in a *.vue file:
export default {
data() {
return {
message: Math.random()
}
}
}
I tried to do console.log(app) in the JS console of the page that that corresponds to and got a Uncaught ReferenceError: app is not defined error so how could I do the same thing in the production code?
You can access the root instance from JS console with:
document.getElementById('app').__vue__.message
or
app.$options.data().message
For inspecting vue SFC, it is better to use Vue Devtools.
Sounds like the Vue.js Devtools extension might be beneficial for you, it'll allow you to see the values of all variables that are available to the Vue template (so everything in data).
https://devtools.vuejs.org/guide/installation.html
You can reference that value doing console.log(this.message). If you want to log the value every time it changes, you can create a watcher for the message and include "console.log(this.message)" in there.
watch: {
message() {
console.log(this.message)
}
}

Avoid app logic that relies on enumerating keys on a component instance

in my complex Vue project I am getting this console warning:
[Vue warn]: Avoid app logic that relies on enumerating keys on a component instance. The keys will be empty in production mode to avoid performance overhead.
Unfortunately I can not find the reason for this warning just by the above message.
How can I track down the reason for this warning?
Check if your watching an entire route object anywhere in your code. Doing so throws that error (in my case).
Refer this vue documentation on watching routes
Accessing router and current route inside setup
The route object is a reactive object, so any of its properties can be watched and you should avoid watching the whole route object. In most scenarios, you should directly watch the param you are expecting to change.
Was able to fix this with the suggestion done by Glass Cannon.(https://stackoverflow.com/a/70205284/11787139)
To clarify and maybe help someone else: I was trying to send an Axios request to the server of which the data I sent through was composed of a direct component reference emitted by the component function.
Component
saveItem(){
this.saved = true;
setTimeout( this.resetState, 2500);
this.$emit('saveitem', this)
},
Parent
saveitem(e){
const data = {item : e}
axios.post(target, data, {headers . . .).then((response) => {}
})
The error disappeared when I instead fetched the index of the list item by doing so:
saveitem(e){
let item;
this.items.forEach( function(item, index, array) {
if(item.id == e.id) pointer = item
})
data.item = pointer
axios.post(target, data, {headers . . .).then((response) => {}
})
}
So I was also having this issue, but not for the reasons the accepted answer provided. It was occurring due to my Vuex store. After a lot of digging I discovered the cause was the presence of the "CreateLogger" plugin.
So if you're having this issue and it's not due to you watching an entire route, check if you're using the CreateLogger plugin in Vuex. That might be the culprit.
This happens for me when I pass this to a data object
data() {
return {
updateController: new UpdateController({
reportTo: this
})
}
}
This used to work fine with Vue 2 but causes this error in Vue 3.
Making this modification solved the problem for me.
data() {
return {
updateController: new UpdateController({
reportTo: () => this
})
}
}
I know this might be anti-pattern but I needed to inject partial reactivity to a non-reactive part of a JS library and this was the most not complicated way of achieving this that I can think of.
This happens to me when destructuring a ref without .value.
This was happening to me only in Firefox, and when I removed the Vue Dev Tools extension it stopped. After re-installing Vue dev tools it hasn't come back. Make sure you have the latest version of the Vue Dev Tools for your browser.

VueJs - $route not available on page load

I seem to have an issue with Vue, I'm running it vie Vue UI which is handling the compiling. I'm trying to solve an issue I have VueJs - Passing query in query string as prop but I have noticed the below and I am not sure why.
URL = http://localhost:8080/?q=This%20is%20my%20query
mounted () {
console.log(this.$route.query.q)
console.log(this.$route.query)
}
Given the above url and the console.log the below outputs are happening. I can't figure out why the results are not the same
First visit to the url
undefined
Object { }
After recompile and Vue UI hotreloads
This is my query
Object { q: "This is my query" }
Why can't I see this.$route on the first load?

Accessing vue-axios inside Vuex module actions

In my Vuex setup, the store is currently structured like this:
store
- modules
- common_data
- index.js
- mutations.js
- actions.js
- getters.js
Now, one of the actions inside actions.js is defined as:
populateTimeZones(context) {
var baseUrl = context.getters.getApiBaseUrl;
this.$http.get(baseUrl + '/time-zones')
.then(function (res){
if(res.status == 'ok'){
this.$store.commit('SET_TIME_ZONES', res.info.timeZones);
} else {
alert('An error occurred. Please try again!');
return;
}
}.bind(this));
}
I think the Vue instance is not available here, which is causing the action to fail with the error: Cannot read property 'get' of undefined. I've tried other combinations like this.axios and vue.axios but the result is same.
Am I doing something wrong? What is the common pattern for handling such cases?
You won't be able to access the Vue instance without passing it through or creating a new one.
A simple way to do what you want is to simply pass your this through to your action this.$store.dispatch('populateTimeZones', this), then change your method signiture to populateTimeZones({ context }, vueInstance). This would then allow you to access vueInstance.$http.
Another idea would be something called vue-inject which is a DI container for Vue. It would allow you to register axios as a service and then simply call VueInjector.get('axios') whenever you need it. On the Vue component itself you can do dependencies: ['axios'] and then use like this.axios. Not so much an issue in this case but helpful when you have lots of services doing work for you

Access Vue.js plugin from main.js

I'm creating a plugin and I just wonder why I can't access it in main.js file. Here's how Auth.js looks like:
const Auth = {
install(Vue) {
Vue.prototype.$isGuest = function () {
console.log('This user is a guest.');
}
Vue.prototype.$getAuthToken = function () {
console.log('Auth token will be returned.');
}
}
}
export default Auth
This is main.js:
import Auth from '#/helper/Auth'
Vue.use(Auth)
However, when I execute console.log(this.$isGuest()), it doesn't work. It actually returns the following:
main.js?1c90:25 Uncaught TypeError: this.$isGuest is not a function
The problem is that this method works when I call it in components such as Dashboard.vue and things like that.
I have a way to avoid calling isGuest method within main.js (I can call it in Layout.vue), but I'm more curious why it doesn't work in main.js.
Maybe because Vue hasn't been initialized yet, but even if I put the console.log() line at the end of the file, still doesn't work.
Thanks,
N.
If you are calling this.$isGuest() outside of Vue, you will get the error you describe. That's because this is not a Vue object. What this is depends on how you are building your code, but given you are using import it's probably the module.
Also, you are adding $isGuest to the prototype of Vue. That means that the function is only going to be available on actual instances of Vue objects. That is why it is available in your components.
If you want to use it in the main script, the only place you will be able to get to it is inside the Vue object in a lifecycle handler, method, or computed. For example:
new Vue({
mounted(){
console.log(this.$isGuest()) // this should work
}
})