TypeError: Cannot read properties of undefined (reading 'state') in vuex - vuejs2

Getting this error while using mapState in vuex
computed: mapState(['count'])
where else it is working fine when use like below:
computed: {
count () {
return store.state.count
}
}

This happens due to version issue. After downgrading to vuex 2^ its working fine.

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)
}
}

nuxt, ...mapState value is returned as undefined

I fetch an api in my page's fetch() hook and then through an action and a mutation I update a value in my state called movieList. I know actions and mutations work because I can see them logging the response object correctly. But my page doesn't seem to find movieList in my store so it returns undefined. This is my folder structure:
This is my state:
const state = () => ({
movieList: 'pashmi'
});
pelase note I initialized movieList: 'pashmi' to test to see if ...mapState returns pashmi or not but it still returns undefined. This is my mapState:
import { mapState } from "vuex";
computed: {
...mapState("movies", ["movieList"]),
}
Rename movies.js to index.js, should work.

Why I'm Facing the error [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"

This is a Laravel & Vue Js Project.
Everything works fine but why I'm facing [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined" type error.
My Vue File
<template>
<p>Sold By: {{product.user.name}}</p>
</template>
<script>
export default {
data(){
return {
product:{},
}
},
methods: {
loadData(){
axios.get('/api/'+this.$route.params.slug+'/product')
.then(response => {
this.product = response.data;
},
()=> {});
}
},
created(){
this.$Progress.start();
this.loadData();
this.$Progress.finish();
},
}
</script>
My Controller
public function getProduct($slug)
{
$product = Product::where('slug',$slug)->with('brand','category','subCategory','productImages','featureDescriptions','colors','variants','user')->first();
return response()->json($product, 200);
}
``
Now I want to show my User name in Vue file <p>Sold By: {{product.user.name}}</p>. It showing User Name With an error [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined". when I show the user data <p>Sold By: {{product.user}}</p>, It show user all data without error. Now how i show user name without error.
The error is self-explanatory: you're using {{product.user.name}} in the template. But before the product has returned from BE, product.user is undefined and therefore does not have a .name property.
The simplest fix would be to place a v-if on the <p>:
<p v-if="product.user">Sold By: {{product.user.name}}</p>
Another generic solution for this type of problem is to use a computed:
<template>
<p>Sold By: {{productUserName}}</p>
</template>
<script>
export default {
// ...
computed: {
productUserName() {
return this.product.user?.name || '';
}
}
// ...
}
</script>
You can read more about optional chaining operator (used above) (?.) here.
Because it's a fairly new addition to JavaScript, Vue doesn't currently support it in <template> tags (but it works in <script>).
Additional note: a common mistake is to add an additional data member instead of using the source of the error (product.user in this case) either directly or through a computed. This creates two problems:
it decouples product.user from rendering the <p>. Which means that if BE returns a product without a user, you'll still get the error, because you've set dataLoaded to true but the template still tries to read the property .name of user, which is falsy and therefore does not have a .name.
you create unnecessary boilerplate: anyone trying to understand or modify your code at a later time has to figure out the arbitrary connection between dataLoaded and product.user.
One of the reasons Vue is loved for is because it doesn't require boilerplate code, unlike other frameworks (i.e: Angular). Keep it that way! By using v-if="product.user" in the template, someone reading that code will immediately understand the rendering logic, without having to look at the component code. Decreasing the time needed to figure out the code on a regular basis will greatly decrease the time needed to modify it, should you (or someone else) ever need to. This results into more flexible, more scalable code. Less bugs, less time spent => more money.
This is happening because <p> is being rendered while product is still an empty object (product: {}).
You could use v-if to render only if product already has been loaded.
<template>
<p v-if="dataLoaded">Sold By: {{ product.user.name }}</p>
</template>
<script>
export default {
data() {
return {
product: {},
dataLoaded: false,
};
},
methods: {
loadData() {
axios.get("/api/" + this.$route.params.slug + "/product").then(
(response) => {
this.product = response.data;
this.dataLoaded = true;
},
() => {}
);
},
},
created() {
this.$Progress.start();
this.loadData();
this.$Progress.finish();
},
};
</script>

As soon I add "props" to the component I get: Error in callback for watcher "function () { return this._data.$$state }"

I get a very strange error which I can't locate.
[Vue warn]: Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers."
I am using vuex in strict mode. Despite the error I am not mutating any vuex store state outside mutation handlers. The component is not using vuex at all. I created a test component that does not use anything like below.
<template>
<div>
TEST COMPONENT
</div>
</template>
<script>
export default {
name: 'testComponent',
props: ['testProp'],
}
</script>
As soon I add the props part I get the error. I am not able to represent the whole project here or reproduce it. But there is nothing special anyway.
For me it was because I did routes = this.$router.options.routes for setting up Navigation.
The solution was routes = JSON.parse(JSON.stringify(routes)) before assigning routes to state.
Well after some debugging I found out that it actually was caused by vuex and vue-router.
Actually I could find this before if I just looked detailed into the trace of the error. The vue-router.esm.js?8c4f:2279 section was giving a hint but I could not see it (lack of vue experience I guess).
...
reactiveSetter # vue.runtime.esm.js?2b0e:1055
normalizeProps # vue.runtime.esm.js?2b0e:1449
mergeOptions # vue.runtime.esm.js?2b0e:1521
Vue.extend # vue.runtime.esm.js?2b0e:5159
extractGuard # vue-router.esm.js?8c4f:2279
eval # vue-router.esm.js?8c4f:2263
eval # vue-router.esm.js?8c4f:1968
eval # vue-router.esm.js?8c4f:1968
...
I was getting the the routes from the store and adding (addRoutes()) them to the route.
router.beforeEach((to, from, next) => {
...
router.addRoutes([store.getters['route/getRoute']]);
...
}
But because it was passed by reference (and I guess the router was doing some changes on it) the error was rising. The route was trying to "mutate vuex store outside mutation hander"
[Vue warn]: Error in callback for watcher "function () { return
this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside
mutation handlers."
I solved it by deep cloning (like below) it with lodash but could use other deepcloning as well.
let routeDeepClone = _.cloneDeep([store.getters['route/getRoute']]);
router.addRoutes(routeDeepClone);
Now it works very well. Hope it helps someone.
I was dumbfounded by this for a little while, but turns out it was something super silly. As the error suggests, we are modifying a Vuex state somewhere inadvertently. Possibly, you are doing an assignment without realizing it. My error was this:
computed: {
foo() {
return this.model.bar.find(
(obj) => obj.key = this.$route.params.baz
)
},
}
Silly me, I was doing
obj.key = this.$route.params.baz
instead of
obj.key === this.$route.params.baz
The object was getting updated by reference instead of my intention of doing an equality check.

VueJS - route.go doesn't work

When i try redirect to other router in watcher, console gives me this error:
Can somebody help me and tell why is this happening?
Thanks!
watch: {
lifes : function() {
console.log('lifes watcher work')
if(this.lifes === 0) {
this.$route.router.go('/ending');
}
}
},
I find other ways like this.router.go('/ending') or just router.go('/ending') but also doesn't work.
ERROR:
[Vue warn]: Error in callback for watcher "lifes": "TypeError: Cannot read property 'go' of undefined"