4

I've become frustrated with finding an example for what I thought would be a really common use case for something like Vuex.

I dispatch an asynchronous action on the store to populate it via api. Once this store is populated I need to then execute certain operations.

Every Vuex example I come across seems to just deal with a straight update to the UI. But in almost every case I need to also perform key component based operations.

state: {
  // initial state values are all falsey
  id: false,
  name: false,
},
getters:   {
  getItem: (state) => {
    return state;
  },
},
actions: {
  setItem({commit}) {
    // async call to get and then commit the state
  }
}

Above is the relevant snippet of the item store a very simple example where the call to dispatch the action is typically called from a component not detailed here. Below is the component where I'm watching for the item to be populated.

watch:    {
  item: function (newItem) {
    this.doSomethingWith(newItem);  // this never runs
  }
},
computed: {
  ...mapGetters({
    item: 'getItem',
  }),
},
mounted() {
  console.log(this.item);  // I get an observer of the item object

  // none of items state properties are defined during mounted
},
methods: {
 doSomethingWith(item) {
   // I want to do something here with the set item!!
 }
}

I expect the items state not to be set on mount as it's an async call to an external api. However what I did expect is when it is eventually populated the watcher would catch that and allow me to run subsequent operations inside the component. However the watch doesn't ever fire.

So how do I track changes like this in components and run operations dependant on their new state?

2
  • You've mapped item to a getItem getter, but your example has a getUnit getter. Commented Sep 22, 2017 at 15:51
  • That was a typo - I'm copying code from an existing app and trying to make it more general. I've updated the Question. Commented Sep 22, 2017 at 15:56

1 Answer 1

2

The watch never fires because the code is watching the object returned from getItem, which is the state object and the reference to the state object doesn't change. Only the state object's properties change. If you want to fire the watch, you need to perform a deep watch.

watch:    {
  item: {
    handler:function (newItem) {
      this.doSomethingWith(newItem);
    },
    deep:true
  }
},

Depending on your application this might not be very performant. You might want to use a getter that watches a specific property of the state.

Or, return a promise from an action that kicks off the asynchronous API call and do what you need to in a success handler.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah thank you! Reading the docs on the deep option it seems this isn't necessary for arrays which I'm probably more used to watching hence the confusion. The problem with returning a promise from the action is I often call the action in a totally different component (e.g. a parent component and the above example component would be a far off child that needs to respond). I could of course fire an event using a global event bus but I feel that kind of defeats the purpose of using Vuex.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.