I'm using vuex-presistedstate
in my project. In the source code on github the plugin calls store.replaceState
to hydrate store from storage. Is there a way to know when the store hydrates?
The vuex-presistedstate
plugin has a configuration option called rehydrated
that allows you to pass a function that will be called immediately after replaceState
. If you only care about calls to replaceState
from that plugin then that should fit your needs nicely.
I don't believe the store itself provides a 'hook' for when replaceState
is called. The method replaceState
is implemented here:
https://github.com/vuejs/vuex/blob/e0126533301febf66072f1865cf9a77778cf2176/src/store.js#L183
As you can see from the code it doesn't do much. Even subscribers registered using subscribe
aren't called. However, you could potentially use watch
to register a watcher on a specific property within the state and use that to detect when the state is replaced:
https://vuex.vuejs.org/api/#watch
Of course you'd need to be careful to structure things so that only the calls to replaceState
trigger the watcher, which may get fiddly.
A further alternative would be to patch/override the replaceState
method. Replace it with your own method that calls out to the original, giving you a hook point for any extra functionality you might need.
I've attempted to demonstrate all of the above in the example below:
// Can't use localStorage in an SO snippet...
const fakeStorage = {
vuex: `{"flag": {}, "number": ${Math.random()}}`
}
const storage = {
getItem (key) {
return fakeStorage[key]
},
setItem (key, value) {
fakeStorage[key] = value
},
removeItem (key) {
delete fakeStorage[key]
}
}
// Override replaceState with our own version
class StoreOverride extends Vuex.Store {
replaceState (...args) {
super.replaceState(...args)
console.log('replaceState called')
}
}
const store = new StoreOverride({
state: {
flag: {},
number: 0
},
plugins: [
createPersistedState({
rehydrated () {
console.log('rehydrated called')
},
storage
})
]
})
store.subscribe(() => {
console.log('store.subscribe called (will not happen for replaceState)')
})
store.watch(state => state.flag, () => {
console.log('store.watch called')
})
console.log('creating Vue instance')
new Vue({
el: '#app',
store,
methods: {
onReplace () {
// The property 'number' is changed so we can see something happen
this.$store.replaceState({
flag: {},
number: this.$store.state.number + 1
})
}
}
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script>
Vue.config.devtools = false
Vue.config.productionTip = false
</script>
<script src="https://unpkg.com/[email protected]/dist/vuex.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vuex-persistedstate.umd.js"></script>
<div id="app">
<button @click="onReplace">Replace</button>
<p>{{ $store.state.number }}</p>
</div>