Vuex: Cloud add dispatch interface on getter?

Created on 7 Apr 2017  路  5Comments  路  Source: vuejs/vuex

What problem does this feature solve?

I used to such an usage:

computed: {
  ...mapGetters([ 'books', 'booksStatus' ]),
  theBooks () { // Use this.theBooks instead the this.books in render function
    if (this.booksStatus === null) this.fetchBooks()
    return this.books
  }
},
methods: {
  ...mapActions([ 'fetchBooks' ]) // ajax request
}
// vuex stuff

const state = {
  books = [],
  booksStatus = null, // null | 'success' | 'failed'
}

const actions = {
  fetchBooks: ({ commit }) => {
    // do: state.booksStatus = null
    commit('FETCHBOOKS_REQUEST')

    fetch ('url')
    // do: state.booksStatus = 'success', state.books = books
    .then(res => { commit('FETCHBOOKS_SUCCESS', res.books)})
    // do: state.booksStatus = 'failed'
    .catch(err => { commit('FETCHBOOKS_FAILURE') })
  }
}

This way avoids to write dump created () { this.fetchBooks() } or watch: { $route () { this.fetchBooks() } } and once you need this.books, computed fetches this data automatically.
In another situation, container(vue component) A and container B both needs this.$store.state.books, I have to rewrite computed propertytheBookstwice while I dont' know which container will pull the data forstate.books` first.

What if add an interface on getters for dispatch fetching in getter, then all need to do in other containers is just to add getters in computed ?

const getters = {
  books: ({ state, getters, dispatch}) => {
    if (getters.booksStatus === null) dispatch('fetchBooks')
    return state.books
  }
}

I know the getter is designed as a pure function but why it must be that? Can we add dispatch in getter?

What does the proposed API look like?

vuex getters receive prarams:

  • state,
  • getters,
  • rootState,
  • dispatch
proposal

Most helpful comment

@LinusBorg Thanks for reply, I know the getter is designed obeying no side effects principle, in real project, people used to using vuex to manage global states, but how to elegantly fetch remote data and store it?
I think a sound way is like this, simulate the promise working mechanism, dataStatus is a state which represents the remote data process status, data getter is computed from data state and be accessed by compoent. At first, data getter return the default value and once this api fetcher fullfilled the fetching process, dispatch an action which mutate the dataStatus and the data, and the getter reflect the new value and dataStatus imediately.
I have thinked of that vuex may won't actually add dispatch on getter which break the vuex desgining philosophy. But could you or someone teach me some practices to handle api fetchers? If A, B, C components require a common state books, how and what is the principle to decicde which one dispatches fetching action? And how to dispatch fetcher actions? In created function? In watch interface? And every compoents need a data getter have to import the fetching action? Will a fetchers be called many times by each component and a state be setted many times?

All 5 comments

Hi @zheeeng,

Thanks for your suggestion.

Getters are computed properties, and those should not have side effects. Also, dial sticking actions from getters would make the interface and data flow of your app harder to track, because there is not indication in a component where the dispatch is done, you have to know to look in the getter.

I don't think that this is a good idea.

@LinusBorg Thanks for reply, I know the getter is designed obeying no side effects principle, in real project, people used to using vuex to manage global states, but how to elegantly fetch remote data and store it?
I think a sound way is like this, simulate the promise working mechanism, dataStatus is a state which represents the remote data process status, data getter is computed from data state and be accessed by compoent. At first, data getter return the default value and once this api fetcher fullfilled the fetching process, dispatch an action which mutate the dataStatus and the data, and the getter reflect the new value and dataStatus imediately.
I have thinked of that vuex may won't actually add dispatch on getter which break the vuex desgining philosophy. But could you or someone teach me some practices to handle api fetchers? If A, B, C components require a common state books, how and what is the principle to decicde which one dispatches fetching action? And how to dispatch fetcher actions? In created function? In watch interface? And every compoents need a data getter have to import the fetching action? Will a fetchers be called many times by each component and a state be setted many times?

But could you or someone teach me some practices to handle api fetchers?

That would be a great question to ask on our forums, I'm pretty active there: forum.vuejs.org

We have a rule not to do support in github issues to keep them focused on bugs & new features, so we can't discuss this here.

If it's ok for you, I will close this issue since I think we agree that your suggestion doesn't really fit with vuex principles.

After a while thinking, in my practice, may datastatus be setted as one of null, 'pending', 'success', 'failed' be nicer.

If getter can access dispatch interface, null be the initial value of dataStatus, getter dispatch fetching action if the dataStatus is null. Fetching action trigger corresponding mutation to set the status and data.

In generally we have not to import datastatus and fetching action into components unless you intend to watch the status changing for dispalying data fetching effects (through watch interface) or bind fetching actions on button click event (through methods interface). When we write a component, just use mapGetters if it needs the state, getter handles all things and once the value is updated, state triggers the component rerendering.

@LinusBorg Sorry for discuss these in improper place. You can close this issue and I will post these thoughts in forum.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Ge-yuan-jun picture Ge-yuan-jun  路  3Comments

jdittrich picture jdittrich  路  3Comments

weepy picture weepy  路  3Comments

matthewmorgan picture matthewmorgan  路  3Comments

gorbypark picture gorbypark  路  3Comments