Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
462 views
in Technique[技术] by (71.8m points)

javascript - Error in render function: “TypeError: Cannot read property of undefined”, using Vuex and Vue Router

I have been dealing with an issue using Vue, Vuex and Vue-Router. I'm building a flash cards app, fetching all the cards on main app creation, then using a Vuex getter to get each card by its id which is passed as a route parameter.

Relevant bits:

App.vue

export default {
  components: {
    'app-header': header,
  },
  data() {
    return {
    }
  },
  created() {
    this.$store.dispatch('getAllCards');
  }
}

The dispatch('getAllCards') is just pulling all the cards from the DB and committing to Vuex store.js.

Now I set up a getter:

getters: {
  cardById: (state) => (id) => {
    return state.allCards.find((card) => card._id === id);
  }
}

Here is 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>

I am getting the TypeError referenced in the title. My understanding is that the created() hook happens after data() has been set up, so then I can assign {card} using the getter. Unfortunately this displays nothing...

If I assign card() as a computed property:

computed: {  
  card() {
    return this.$store.getters.cardById(this.$route.params.id);
  }
}

The card shows, but I still get that error in console. Any idea why? I looked at this and attempted that solution, but to no avail.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The question don't have all the premise to get a correct answer. (We don't know the mutations, the state, neither the actions and we have no clues about app-header component) So we have to admit some hypothesis :

  1. state.allCards is an empty Array when you mount the component
  2. action getAllCards is an async function to retrieve or set state.allCards with a mutation

cardById's getters, return a function, so vuex can't apply reactive on a function. So if the state change, the getter won't be trigger correctly. To correct this, use computed as you mention here.

But it don't fix the undefined error, that from my point of view, is because the getters return undefined on mount.

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'
    };
  }
}

You can see the implementation on this jsfiddle with no error on console.

Or you can have a loading state on undefined value for your card component.

If my hypothesis is wrong please provide a jsfiddle to help you.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...