VueJS: Computed Property Is Calculated Before Created in Component?

Viewed 6049

I have a component, which looks like this:

export default {
  name: 'todos',
  props: ['id'],
  created () {
    this.fetchData()
  },
  data() {
    return {
    }
  },
  computed: {
    todos () {
      return this.$store.state.todos[this.id]
    }
  },
  methods: {
    async fetchData () {
      if (!this.$store.state.todos.hasOwnProperty(this.id)) {
        await this.$store.dispatch('getToDos', this.id)
      }
    }
  }
}

This is what's happening:

  1. The component receives an id via props.

When the component loads I need to fetch some data based on the id

  1. I have a created() hook from where I call a function fetchData() to fetch the data.

  2. In methods, the fetchData() function dispatches an action to get the data. This gets and stores the data in Vuex store.

  3. The computed property todos gets the data for this id.

The problem is that when the page first loads, the computed property todos shows up as undefined. If I change the page (client side) then the computed property gets the correct data from the store and displays it.

I am unable to understand why computed property doesn't update?

3 Answers

You could use following approach:

component.vue (and just render todoItem)

  methods: {
    async fetchData () {
      const _this = this;
      if (!this.$store.state.todos.hasOwnProperty(this.id)) {
        this.$store.dispatch('getToDos', {id: this.id, callback: () => {
          _this.todoItem = _this.$store.state.todos[_this.id]
        }});
      }
    }
  }

store.js

  actions: {
    getToDos: (context, payload) => {
      // simulate fetching externally 
      setTimeout(() => {
        context.commit("getToDos__", {newId: payload.id, task: "whatever" });
        payload.callback();
      }, 2000);
    },

Base on here

When this hooks is called, the following have been set up: reactive data, computed properties, methods, and watchers. However, the mounting phase has not been started, and the $el property will not be available yet.

I think what might solve it is if you create a getter for todos.

So in your VueX Store add:

getters: {
    todos(state) {
        return state.todos;
    }
};

And than in your computed use:

computed: {
    todos () {
        return this.$store.getters.todos[this.id]
    }
}
Related