VueJS: Computed Property Is Calculated Before Created in Component?
Asked Answered
L

3

7

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?

Luxe answered 26/10, 2018 at 10:45 Comment(5)
Can you show the code for the getToDos function aswell?Wylen
@T.Dirks getToDos is a Vues action that calls an external api for the data and then commits a mutation. getToDos ({commit}, payload) { return api.content.gettodos(payload.is) .then(response => { commit('SET_TODOS', response) return response }) .catch(error => { console.log(error) return error }) }Luxe
My own understanding of the problem is that the computed is already set before we even call the method. And at that time, the store doesn't have the data. Later on, the method is called and the store is filled. But I don't know how to correct it.Luxe
You could trigger the fetchData function from your root component (App.vue), so all other components can work with that data and use fetchData in the components to update the data.Yep
For now, I've chosen to solve the problem by preponing where I call the fetchData() and the issue is temporarily resolved. However, I would like to keep the question open as I really intend to understand what's going on here.Luxe
M
1

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);
    },
Muhammadan answered 26/10, 2018 at 11:49 Comment(2)
I think this will work, but why should we have to do this? Why can' I update the computed property value in some other way?Luxe
I don’t know how you’re updating the store but I’m asuuming you’re just updating an index in an array directly. vue can’t monitor such changes so you’ll have to use a trick described here vuejs.org/v2/guide/list.html#CaveatsMuhammadan
T
0

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.

Tenorio answered 17/8, 2022 at 14:35 Comment(0)
W
-1

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]
    }
}
Wylen answered 26/10, 2018 at 11:5 Comment(2)
I tried this but it doesn't solve the problem. In some other threads I read suggested to add a watcher but I'm not sure how to do that.Luxe
A watcher won't do you any good I think, can you perhaps edit your question to show all the relevent code? So the component which uses it, the dispatch methods and the mutation methods? If you show all the relevant parts we might get a better understanding of where the problem isWylen

© 2022 - 2024 — McMap. All rights reserved.