Search code examples
javascriptvue.jspromisevuex

Prevent persisted state locking up app in VueX


I'm using the vuex-persistedstate module to keep track of my state and persist it to localStorage. The problem is that due to the amount of state that needs to be saved, the app gets locked up every time an update to my data occurs.

In order to solve that, I'm trying to use a promise to allow business calculations to be performed whilst the string is being generated. Once the string is ready, it should then be set to localStorage.

This is what I have:

const buildLocalStorageString = async (state) => {
  return await JSON.stringify(state);
}

export default new Vuex.Store({
  state: { etc, etc, etc },

  plugins: [createPersistedState({
    key: 'myApp',
    setState (key, state, storage) {
      buildLocalStorageString(state).then(string => {
        storage.setItem(key, string) 
      }) 
    }
  })],
})

Problem is, it doesn't solve the problem. There is still a noticeable delay when the app updates.


Solution

  • All localStorage calls are synchronous. And Javascript is single threaded. Saving 1 large chunk of data into local storage is always going to block all other execution.

    I would solve this by splitting the data and saving it into local storage separately. Basically, just use multiple createPersistedState.

    An extremely simple example implementation could look like this

    import Vue from 'vue'
    import Vuex from 'vuex'
    import createPersistedState from "vuex-persistedstate";
    
    Vue.use(Vuex)
    
    const moduleA = {
        state: {
            a: 'a'
        },
        mutations: {
            updateA(state) {
                state.a += 'a';
            }
        }
    }
    
    const moduleB = {
        state: {
            b: 'b'
        }
    }
    
    export default new Vuex.Store({
        modules: {
            moduleA: moduleA,
            moduleB: moduleB
        },
        plugins: [createPersistedState({
            key: 'vuex_a',
            paths: ['moduleA']
        }), createPersistedState({
            key: 'vuex_b',
            paths: ['moduleB']
        })]
    })