Error in render function: “TypeError: Cannot read property of undefined”, using Vuex and Vue Router
Error in render function: “TypeError: Cannot read property of undefined”, using Vuex and Vue Router
我一直在使用 Vue、Vuex 和 Vue-Router 处理一个问题。我正在构建一个闪存卡应用程序,在创建主应用程序时获取所有卡片,然后使用 Vuex getter 通过作为路由参数传递的 ID 获取每张卡片。
相关位:
App.vue
export default {
components: {
'app-header': header,
},
data() {
return {
}
},
created() {
this.$store.dispatch('getAllCards');
}
}
dispatch('getAllCards')
只是从数据库中提取所有卡片并提交给 Vuex store.js
。
现在我设置了一个getter
:
getters: {
cardById: (state) => (id) => {
return state.allCards.find((card) => card._id === id);
}
}
这里是Card.vue
:
<template>
<div>
<br>
<div v-if="flipped" class="container">
<div class="box">
<pre v-if="card.code"><code class="preserve-ws">{{card.back}}</code></pre>
<p class="preserve-ws center-vertical" v-else>{{card.back}}</p>
</div>
</div>
<div v-else class="container">
<div class="box">
<h1 class="title has-text-centered center-vertical is-2">{{card.front}}</h1>
</div>
</div>
</template>
<script>
export default {
data() {
return {
card: {},
flipped: false,
general_card: false,
code_card: true,
random_card: false
}
},
computed: {
},
methods: {
},
created() {
this.card = this.$store.getters.cardById(this.$route.params.id);
}
}
</script>
我收到标题中提到的 TypeError。我的理解是 created()
挂钩发生在 data()
设置之后,因此我可以使用 getter 分配 {card}
。不幸的是,这什么也没显示...
如果我将 card()
分配为计算 属性:
computed: {
card() {
return this.$store.getters.cardById(this.$route.params.id);
}
}
卡片显示了,但我仍然在控制台中收到该错误。知道为什么吗?我查看了 this 并尝试了该解决方案,但无济于事。
我认为是这一步抛出错误
getters: {
cardById: (state) => (id) => {
return state.allCards.find((card) => card._id === id);
}
}
在这一步,它找不到汽车的_id,因为allcards是null
;
然后你用computed代替,当allcards被改变时,它会再次获得;
你可以像这样更改代码
getters: {
cardById: (state) => (id) => {
return state.allCards.find((card) => card && card._id === id);
}
}
$route.params.id
一定是string
,那么card._id
是什么类型呢?似乎每个 card._id
都是 number
,我想。
您需要的是基于存储状态的派生状态,即 return 基于卡 ID 过滤的卡。该 id 通过路由参数接收到您的组件。所以最好使用计算 属性 而不是将参数传递给商店 getters
而不是在数据 属性 中初始化 card
使 card
计算 属性 像这样:
computed:{
card(){
return this.$store.state.allCards.find((card) => card._id === this.$route.params.id);
}
}
注意这个
如果一个组件需要基于它自己的状态(在你的例子中是路由参数)派生存储状态,它应该定义一个本地计算 属性
我试过其他人的解决方案,但没有用。但我终于让它工作了。这是对我有用的:
我最终包括了一个顶级:
<div v-if="!card"> Loading card... </div>
<div v-else> Rest of card template </div>
这似乎消除了错误。此外,该卡作为计算 属性:
card() {
return this.$store.getters.cardById(this.$route.params.id);
}
该题不具备获得正确答案的所有前提。
(我们不知道突变、状态,也不知道动作,我们也没有关于 app-header 组件的线索)
所以我们不得不承认一些假设:
state.allCards
挂载组件时Array
为空
- action
getAllCards
是一个异步函数,用于检索或设置 state.allCards
带有突变
cardById
的getters,return一个函数,所以vuex不能对一个函数应用reactive。因此,如果状态发生变化,getter 将不会被正确触发。
要更正此问题,请像您提到的那样使用 computed
.
但它没有修复 undefined error
,从我的角度来看,这是因为 getters return undefined
挂载。
getters: {
cardById: (state) => (id) => {
var card = state.allCards.find((card) => card._id === id);
if(card) {
return card;
}
// on undefined return a default value
return {
front:'default value'
};
}
}
你可以在这个 jsfiddle 上看到实现,在控制台上没有错误。
或者您可以为卡片组件设置未定义值的加载状态。
如果我的假设是错误的,请提供一个 jsfiddle 来帮助你。
我一直在使用 Vue、Vuex 和 Vue-Router 处理一个问题。我正在构建一个闪存卡应用程序,在创建主应用程序时获取所有卡片,然后使用 Vuex getter 通过作为路由参数传递的 ID 获取每张卡片。
相关位:
App.vue
export default {
components: {
'app-header': header,
},
data() {
return {
}
},
created() {
this.$store.dispatch('getAllCards');
}
}
dispatch('getAllCards')
只是从数据库中提取所有卡片并提交给 Vuex store.js
。
现在我设置了一个getter
:
getters: {
cardById: (state) => (id) => {
return state.allCards.find((card) => card._id === id);
}
}
这里是Card.vue
:
<template>
<div>
<br>
<div v-if="flipped" class="container">
<div class="box">
<pre v-if="card.code"><code class="preserve-ws">{{card.back}}</code></pre>
<p class="preserve-ws center-vertical" v-else>{{card.back}}</p>
</div>
</div>
<div v-else class="container">
<div class="box">
<h1 class="title has-text-centered center-vertical is-2">{{card.front}}</h1>
</div>
</div>
</template>
<script>
export default {
data() {
return {
card: {},
flipped: false,
general_card: false,
code_card: true,
random_card: false
}
},
computed: {
},
methods: {
},
created() {
this.card = this.$store.getters.cardById(this.$route.params.id);
}
}
</script>
我收到标题中提到的 TypeError。我的理解是 created()
挂钩发生在 data()
设置之后,因此我可以使用 getter 分配 {card}
。不幸的是,这什么也没显示...
如果我将 card()
分配为计算 属性:
computed: {
card() {
return this.$store.getters.cardById(this.$route.params.id);
}
}
卡片显示了,但我仍然在控制台中收到该错误。知道为什么吗?我查看了 this 并尝试了该解决方案,但无济于事。
我认为是这一步抛出错误
getters: {
cardById: (state) => (id) => {
return state.allCards.find((card) => card._id === id);
}
}
在这一步,它找不到汽车的_id,因为allcards是null
;
然后你用computed代替,当allcards被改变时,它会再次获得; 你可以像这样更改代码
getters: {
cardById: (state) => (id) => {
return state.allCards.find((card) => card && card._id === id);
}
}
$route.params.id
一定是string
,那么card._id
是什么类型呢?似乎每个 card._id
都是 number
,我想。
您需要的是基于存储状态的派生状态,即 return 基于卡 ID 过滤的卡。该 id 通过路由参数接收到您的组件。所以最好使用计算 属性 而不是将参数传递给商店 getters
而不是在数据 属性 中初始化 card
使 card
计算 属性 像这样:
computed:{
card(){
return this.$store.state.allCards.find((card) => card._id === this.$route.params.id);
}
}
注意这个
如果一个组件需要基于它自己的状态(在你的例子中是路由参数)派生存储状态,它应该定义一个本地计算 属性
我试过其他人的解决方案,但没有用。但我终于让它工作了。这是对我有用的:
我最终包括了一个顶级:
<div v-if="!card"> Loading card... </div>
<div v-else> Rest of card template </div>
这似乎消除了错误。此外,该卡作为计算 属性:
card() {
return this.$store.getters.cardById(this.$route.params.id);
}
该题不具备获得正确答案的所有前提。 (我们不知道突变、状态,也不知道动作,我们也没有关于 app-header 组件的线索) 所以我们不得不承认一些假设:
state.allCards
挂载组件时Array
为空- action
getAllCards
是一个异步函数,用于检索或设置state.allCards
带有突变
cardById
的getters,return一个函数,所以vuex不能对一个函数应用reactive。因此,如果状态发生变化,getter 将不会被正确触发。
要更正此问题,请像您提到的那样使用 computed
但它没有修复 undefined error
,从我的角度来看,这是因为 getters return undefined
挂载。
getters: {
cardById: (state) => (id) => {
var card = state.allCards.find((card) => card._id === id);
if(card) {
return card;
}
// on undefined return a default value
return {
front:'default value'
};
}
}
你可以在这个 jsfiddle 上看到实现,在控制台上没有错误。
或者您可以为卡片组件设置未定义值的加载状态。
如果我的假设是错误的,请提供一个 jsfiddle 来帮助你。