Reputation: 6907
If I have two sibling components that share the same data and that data is not already persisted to Vuex
(e.g. a direct page load to api/v1/calendars/:id
, would making a call to that resource within both components be necessary? I have read the following:
Vue components should be as self-contained and isolated as much as possible
If that is true, then requesting the data from Vuex
from within both components is correct, but the application would be making two network calls when only one is required if that data is not already available in Vuex
.
Ideally I would like to make a single network call for the required resource, then multiple components on that page all share the data within Vuex
.
I would be duplicating this code in both components, specifically the created()
method.
<script>
import store from '@state/store'
import { calendarComputed } from '@state/helpers'
export default {
data() {
return {
calendar: null,
}
},
computed: {
...calendarComputed,
},
created() {
// Are calendars already persisted?
if (!this.calendars.length) {
store.dispatch('calendar/getCalendars').then((res) => {
this.calendar = res.find((calendar) => { if (calendar.id == this.$route.params.id) return calendar })
})
} else {
this.calendar = this.calendars.find((calendar) => { if (calendar.id == this.$route.params.id) return calendar })
}
},
}
</script>
Upvotes: 2
Views: 67
Reputation: 23533
The simplest way would be to make your components not (explicitly) care about whether the calendars have been fetched.
Simply tell the store to fetch, but the action decides if it actually needs to do so.
Vuex is supposed to be one-way data flow, so status info does not come back from the action to the component, instead the component always just waits for the data to arrive.
To make things reactive, use a combination of computed
and getter
.
component
created() {
/* tell the store 'this is what I need' */
store.dispatch('calendar/getCalendars');
},
...
computed: {
calendar() {
/* reactive - initially null, then gets a value when the store is updated */
return this.$store.getters['calendar/calendarById'](this.$route.params.id)
},
},
store
getters: {
calendarById: (state) => {
/* return a function so that param can be passed from component */
return (id) => state.calendars ? state.calendars.find(c => c.id === id) : null;
},
}
actions: {
getCalendars (store) {
/* only perform the fetch if the store does not already contain the data */
if (!store.state.calendars) {
fetch(calendarsUrl).then(res => store.commit('setCalendars', res); // e.g
}
},
}
Upvotes: 1