Vuex-persistedstate: Dynamically registered modules

Created on 4 Dec 2017  路  13Comments  路  Source: robinvdvleuten/vuex-persistedstate

It seems to me that this plugin will not work for modules registered dynamically with store.registerModule. Obvious enough for those registered after restoring the state but I usually setup my store empty so it's available immediately and use it e.g. in the router, then I register each module with store.registerModule in a separate file.

It might be worth noting this in the readme that this is not possible. Or maybe you could expose a function to read the state from the storage again so one could invoke it manually once all modules are registered?

Most helpful comment

@chlab, I had this issue too and I solved it by adding the preserveState option to the registerModule function i.e. store.registerModule('a', module, { preserveState: true }). See https://vuex.vuejs.org/en/modules.html#dynamic-module-registration.

All 13 comments

@chlab, I had this issue too and I solved it by adding the preserveState option to the registerModule function i.e. store.registerModule('a', module, { preserveState: true }). See https://vuex.vuejs.org/en/modules.html#dynamic-module-registration.

Good to know, thanks @JaZo. I worked around it by adding the affected module to the store from the start.

I had the same issue and solved it using the solution @JaZo provided.

Actually, there is one slight issue with that work around. If the state has never been initialized on a client, the preserveState flag will keep it from initializing.

We got around it by checking the state for each module and setting to true or false depending on whether the state was already there or not.

I had the same issue with one store module that would be dynamically registered. I ended up creating my own small Vuex plugin that is run after vuex-persistedstate on the application start and compares what data is stored to which modules are registered and if needed reregistered those modules with the preserveState flag set to true.

This way might be a different approach but helped me from changing my whole application and how it dynamically registered those modules.

The following code might help someone else. There are probably better ways to accomplish this, if so please let me know.

main vuex store file:

import createPersistedState from 'vuex-persistedstate'
import reregisterModules from './reregistermodules'
...
  plugins: [
    createPersistedState(),
    reregisterModules()
  ],

The dynamic modules are named "plotModuleX" where X is an incremented integer.

reregistermodules.js:

import plotsModule from './plots'
const {state: statePlotsModule, getters: plotGetters, mutations: plotMutations} = plotsModule

var difference = require('lodash/fp/difference')

export default function () {
  // called when the store is initialized
  return function (store) {
    // show stored data and registered modules / state obects
    // console.log(Object.keys(store._vm._data.$$state))
    // console.log(Object.keys(store._modules.root.state))

    // get modules which state is stored but are not registered
    let diff = difference(Object.keys(store._vm._data.$$state), Object.keys(store._modules.root.state))

    // if it is a plotModule, register it again with preservedState = true
    for (let mod of diff) {
      if (mod.slice(0, 10) === 'plotModule') {
        console.log('reregistering plot module')
        let plotId = mod.slice(10)
        store.registerModule(`plotModule${plotId}`, {
          state: statePlotsModule,
          getters: plotGetters,
          mutations: plotMutations,
          namespaced: true // making our module reusable
        }, { preserveState: true })
      }
    }
  }
}

I had a similar issue. Got round it with a combination of @JaZo's helpful solution, plus registration of dynamic modules in the beforeCreate() hook in App.vue (and deregistration in beforeDestroy() hook).

@chlab, I had this issue too and I solved it by adding the preserveState option to the registerModule function i.e. store.registerModule('a', module, { preserveState: true }). See https://vuex.vuejs.org/en/modules.html#dynamic-module-registration.

Why isn't this in the docs?

@vafl-brut it is:

It may be likely that you want to preserve the previous state when registering a new module, such as preserving state from a Server Side Rendered app. You can achieve this with preserveState option: store.registerModule('a', module, { preserveState: true })
https://vuex.vuejs.org/guide/modules.html#dynamic-module-registration

@chlab No, I meant why isn't it in the docs for this library. I believe it would have been helpful to add it here as well.

@vafl-brut well according to @acan13 there's an issue with it so I don't think it's the intended usage.

@vafl-brut @chlab I have mixed feelings about this. We've stopped using vuex-persisted state because our state is large and it doesn't feel like good practice to be storing tons of things in local storage when a lot of them don't need to be. I feel like vuex-persisted state is best suited for projects with small, simple stores.

The preserveState flag behaves in a way that logically makes sense to me, so it's not so much of an issue as it is a gotcha. Might be nice to have something in the documentation about it, but it does seem outside of the scope of how I think vuex-persisted state should be used.

https://github.com/robinvdvleuten/vuex-persistedstate/pull/225
Feel free to comment / support this PR to handle dynamic registered modules at store creation.

The PR mentioned by @boris-graeff is merged and released in v2.7.0.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kylebradshaw picture kylebradshaw  路  5Comments

rootsli picture rootsli  路  5Comments

metodib picture metodib  路  6Comments

abensur picture abensur  路  4Comments

jerometremblay picture jerometremblay  路  6Comments