Vue lost reactivity - javascript

Can't understand why this simple things not reactive.
Looks like I'm missed some Vue's basis.
<template>
<div>
{{connection_status}}
</div>
</template>
<script>
export default {
data() {
return {
connection_status: 'loading',
};
},
created() {
Echo.connector.socket.on('connect', function(){
this.connection_status = 'connected';
console.log(this.connection_status );
});
Echo.connector.socket.on('disconnect', function(){
this.connection_status = 'disconnected';
console.log(this.connection_status );
});
},
}
</script>
Echo runs throught socket.io and works correct. All events triggers in time.
Console output when connected:
connected
But on page
loading
Same thing when disconnected triggers.
In console:
disconnected
On page
loading

Your problem is that this inside the callback function doesn't refer to the Vue instance. You should use an arrow function instead ..
created() {
Echo.connector.socket.on('connect', ()=>{
this.connection_status = 'connected';
console.log(this.connection_status );
});
Echo.connector.socket.on('disconnect', ()=>{
this.connection_status = 'disconnected';
console.log(this.connection_status );
});
},
Or you could assign this to a variable and use it in the callback function ..
created() {
const vm = this;
Echo.connector.socket.on('connect', function(){
vm.connection_status = 'connected';
console.log(vm.connection_status );
});
Echo.connector.socket.on('disconnect', function(){
vm.connection_status = 'disconnected';
console.log(vm.connection_status );
});
},

In javascript a function is an object. Using function() {} defines a new object scope and therefore a new scope for this. You are assigning the value to the connection_status property on the function, not your vue component.
The best practice is to use arrow functions unless you need a new function scope as arrow functions inherit this from the scope they are defined in.
Echo.connector.socket.on('connect', () => {
this.connection_status = 'connected';
console.log(this.connection_status );
});
Echo.connector.socket.on('disconnect', () => {
this.connection_status = 'disconnected';
console.log(this.connection_status );
});

You should use the mounted() hook instead of the created() one if I understand the doc well : https://v2.vuejs.org/v2/api/#created

Related

cant access data return{} varibles in VueJS

function HeaderreRender() {
HeaderRender = false;
this.$nextTick(() => {
HeaderRender = true;
});
};
export default {
name: 'Home',
components: {
HeaderItem,
},
data: function() {
return {
HeaderRender: true,
};
}
}
this is the code now I want to use v-if="HeaderRender" to re-render the headerItem
but when I call function HeaderreRender()
it is replying to me
Uncaught ReferenceError: HeaderRender is not defined
on the function
any suggestions? on why this happens?
Try to place the HeadereRender() function within the methods object of the component and also, it's this.HeaderRender=true
In simple terms, this method does not know about the HeaderRender variable, thus it is not defined in the scope of the function, written that way

VueJS returns undefined in created function [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
i have started working on a small project using VueJs, i've made a get request using Axios library which returns some data as expected, but I cannot call loadUsers function using this inside mounted
this is my code:
export default{
data(){
return {
users : {}
}
},
methods:{
addCustomer(){
//var form = document.querySelector('#add-customer');
var formData = $('#add-customer').serialize();
axios.post('/Thirdparty', formData).then(function(response){
helper.validation(response.data);
//alert(response.data.error);
});
},
loadUsers(){
axios.get('/Thirdparty/loadUsers').then(function(data){
this.users = data.data;
});
}
},
created(){
let self=this
self.loadUsers();
}
}
as you can see also i've used self variable to call my loadUsers() function, but i'm still getting
this is undefined error
You're referencing this.users within the callback to axios.get().then() in loadUsers(). Due to you're using a standard function and not an arrow function, this is not referring to the Vue instance, i.e. the scope for this is now incorrect. Either use an arrow function or change the reference:
// Do this...
export default{
data(){
return {
users : {}
}
},
methods:{
addCustomer(){
//var form = document.querySelector('#add-customer');
var formData = $('#add-customer').serialize();
axios.post('/Thirdparty', formData).then(function(response){
helper.validation(response.data);
//alert(response.data.error);
});
},
loadUsers(){
axios.get('/Thirdparty/loadUsers').then((data) => { // Using an arrow function.
this.users = data.data;
});
}
},
created(){
let self=this
self.loadUsers();
}
}
// Or this...
export default{
data(){
return {
users : {}
}
},
methods:{
addCustomer(){
//var form = document.querySelector('#add-customer');
var formData = $('#add-customer').serialize();
axios.post('/Thirdparty', formData).then(function(response){
helper.validation(response.data);
//alert(response.data.error);
});
},
loadUsers(){
let self=this; // Adding "self"
axios.get('/Thirdparty/loadUsers').then(function(data){
self.users = data.data; // Referencing "self" instead of "this".
});
}
},
created(){
let self=this
self.loadUsers();
}
}

Calling Vue method from inside mounted function

In my Vue mounted code, I am calling a function test via this.test(). This works fine as intended.
When however I am calling this.test() from the new ResizeObserver function, I am getting an error
this.test is not a function
I understand that this is because the this there is now pointing to the resizeObserver. What I do not understand is what I should use there instead. Removing the this also gives an error.
I have the following Vue code
mounted: function() {
this.test();
new ResizeObserver(function() {
this.test();
}).observe(this.g("tC"));
},
methods: {
test: function() {}
....
}
You should either bind "this" to the function passed to ResizeObserver
mounted: function() {
this.test();
new ResizeObserver(function() {
this.test();
}.bind(this)).observe(this.g("tC"));
},
Or use an arrow function (if your environment supports ES6) since arrow functions use "this" value of the outer scope:
mounted: function() {
this.test();
new ResizeObserver(() => {
this.test();
}).observe(this.g("tC"));
},
It works for me like this
mounted: function() {
$vm = this;
new ResizeObserver(function() {
$vm.test();
}).observe(this.g("tC"));
},
methods: {
test: function() {}
....
}
Use Arrow functions to bind scope
new ResizeObserver(()=> { //--> Arrow Function
this.test();
}).observe(this.g("tC"));

Access component data in Created or Mounted hook

I'm writing a component for Vue.js and I need to modify data on event. But for some reason, when I access it, it's set as undefined
module.exports = {
data: function() {
return {
visible: true
}
},
mounted: function() {
this.eventHub.$on('minimize', function(window_id) {
console.log(this.visible);
this.visible = !this.visible;
});
},
props: ["windowId"]
}
When the event is called for the first time, data.visible is undefined, for some reason.
Is there anything I'm doing wrong?
Thanks!
Because function (window_id) has it's own scope, you can not access this.
This can be solved by adding self = this.
let self = this
this.eventHub.$on('minimize', function(window_id) {
console.log(self.visible);
self.visible = !self.visible;
});
As Nick Rucci pointed out, you can also use an arrow function, and get rid of self = this.
this.eventHub.$on('minimize', (window_id) => {
console.log(this.visible);
this.visible = !this.visible;
});

Vuejs calling a method from $on event

Am building a vuejs component
methods: {
filterPeople: function() {
console.log('hello')
//do some good stuff
},
},
beforeCreate() {
//do some ajax stuff
},
mounted() {
Event.$on('applied', function() {
console.log('the event is being caught')
this.filterPeople();
})
})
The error I get is
this.filterPeople(); is not a function
When I move it outside the Event.$on block it does call the method.
How does this work?
It was all to do with Scope
var self = this;
Event.$on('applied', function() {
self.filterPeople();
})
Use arrow functions to save the context:
Event.$on('applied', () => this.filterPeople());

Categories