New: Populate Vuex store's initial state when creating store
New Pattern Proposal
Initialize Vuex store state by passing it to the store's creation function.
This pattern will be familiar to those who have used Redux.
tl;dr:
// in the Vue app's initialization script
import Vue from 'vue';
import createStore from './stores';
import AwesomeVueApp from './components/awesome_vue_app.vue'
export default () => {
// initial state is stored in the element's data-* attributes
const el = document.getElementById('js-awesome-vue-app');
return new Vue({
el,
// initialize the store with the data from Rails
store: createStore(el.dataset),
render: h => h(AwesomeVueApp)
});
};
Advantages of new pattern
-
Less code. No need to create
setInitialStateactions (and associated mutations/types/specs) like this. -
Simplicity. Currently, during app initialization, data flows through our application like this:
- Rails renders data into the HTML page as
data-*attributes - The Vue app initialization script plucks these values from the page and passes them as props to the root Vue component
- The root Vue component calls
setInitialStateduringcreatedormountedto pass this data to the store
Passing initial state directly to the store allows us to skip step #3 and avoids involving components in this plumbing. - Rails renders data into the HTML page as
-
Consistency (relative to our current state, which is no pattern). Going forward, all Vuex stores would be initialized in the same way.
Disadvantages of new pattern
- No mutation record for the setting of the initial state. For example, no
SET_INITIAL_STATEmutation will be shown in the Vuex dev tools- However, the value of the initial state is still available in the Veux dev tools by clicking "Base State"
- Because initial data is not passed through Vue
props, we losepropsvalidation such as types and existence
What is the impact on our existing codebase?
None. This would only be a guideline for new code.
Reference implementation
This reference implementation shows a conversion of a Vuex store from the setInitialState method mentioned above to the new pattern proposed by this RFC.
There are a couple of things that are unique to this implementation that may not apply to most Vuex stores in our codebase:
- Previously,
setInitialStatewas manually dispatched from the Vue app's initialization script. This is a bit unusual; the most common pattern in our codebase is call this action from a component'screatedormountedhook like this. - This store is used as a module. Most Vuex applications in our existing codebase do not make use of modules.