I have store that initializes its state by action that accessing API. I have one parent and many child components that use the store state as initial state of themselves. Moreover, these components are able to modify the state and send new data to the API.
The problem is that components depend on state and change it — so when they do it, application falls into an infinite loop.
For example (pseudocode):
Store:
state: count = 0
mutations: set (state, count) {state.count = count}
actions:
fetch(context) {
api.get('count').then(res => context.commit('set', res))
}
set_and_save(context, count) {
api.post('save_count', count);
context.state.commit('set', count)
}
Parent component that initializes store data:
mounted () {this.$store.dispatch('counter/fetch')}
Child component:
computed: {
counter () {return this.$store.state.counter.count}
}
watch: {
// This component will be rendered before state initializes from API, so that
// we should watch for counter to update
counter() {this.currentCount = this.counter}
// If we change counter (for example, by pressing the button), we should
// change state and send data to API
currentCount () {
this.$store.dispatch('counter/set_and_save', this.currentCount)
}
}
So when API returns data, counter() recomputes, then currentCount changes, which runs action that changes state, which causes counter() recompute, et cetera. That is the problem.
I think this is common problem, but I did not find anything about it. I tried following things: — To create bool flag and do not run action if it is true (straight, stupid, do not cool); — To unwatch currentCount while we running counter() (weird); — To assure that by the moment we render child component we definitely initialized the state (complicated and it will cause long render); — ???
The one important thing: we cannot use store.state.count directly, because in real task the logic is complicated (state is list, and in component we divide that list into four different lists, render them, and then, when we want to save state, we put them back together and send to action).
So, maybe, that problem hasn't got good solution?