Vuex-persistedstate: how to compatibility with vuex-module-decorators?

Created on 6 Dec 2019  路  2Comments  路  Source: robinvdvleuten/vuex-persistedstate

  • vuex-persistedstate version:^2.7.0
  • vuex-module-decorators version:^0.11.0
  • node version:^10.16.0
  • npm (or yarn) version:^6.9.0

use dynamic mode
when i refresh the page,the state is back to default and the console is warning

1
2

when i click the button,the userNum is add,and the localstorage is work,but when i refresh the page,the userNum is back to the default,and the console is warning

3

close dynamic mode
when i close the dynamic mode and refresh the page,the vuex-persistedstate and vuex-module-decorators are all good

export default new Vuex.Store({
  modules:{
    user:userModule
  },
  plugins:[createPersistedState()]
});
import {getModule} from 'vuex-module-decorators'
import userModule from '@/store/modules/user'

@Component({
  name: "Todo"
})
export default class Todo extends Mixins(Mixins1) {
  private user = getModule(userModule,this.$store)
  private get userNum() {
    return this.user.userNum
  }
  public clickBtn() {
    this.user.addUserNumber(11)
  }

Most helpful comment

Hey there, I came with the following solution by using the preserveState property within the module decorator options. The property value should be true when loading persisted data from local storage (or any other store of choice) and false otherwise, so it uses the initial value since this will be undefined otherwise.

// globals.ts

import SecureLS from 'secure-ls';

export const storageKey = 'vuex';  // the key used by localStorage

export const secureStorage = new SecureLS({ isCompression: false });

const initialStoreContent = secureStorage.get(storageKey); // or localStorage.get(storageKey)
export const initialUnencryptedStorage = initialStoreContent
    ? JSON.parse(initialStoreContent)
    : {};  // parse the localStorage value to an object when it's defined, else set it as an empty object
// store/index.ts

import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';

import { secureStorage } from '@/globals';

Vue.use(Vuex);

// nothing fancy going on here, other than the fact that modules aren't statically inserted into the store object
export default new Vuex.Store({
    plugins: [
        createPersistedState({
            storage: {
                getItem: (key) => secureStorage.get(key),
                setItem: (key, value) => secureStorage.set(key, value),
                removeItem: (key) => secureStorage.remove(key)
            }
        })
    ]
});
// store/modules/userModule.ts

import {
    Module,
    Mutation,
    VuexModule,
    Action,
    getModule
} from 'vuex-module-decorators';

import store from '@/store';

import { initialUnencryptedStorage } from '@/globals';

const name = 'users';

@Module({
    namespaced: true,
    name,
    dynamic: true, // important!
    store, // module is dynamically added to the store here (so after the store was created, instead of during the creation)
    preserveState: Boolean(initialUnencryptedStorage[name]) // preserve state when available from local storage, else don't preserve
})
class UserModule extends VuexModule {
    userNum = 1; // 1 is the initial value when nothing was preserved

    @Mutation
    SET_USER_NUMBER(payload: number) {
        this.userNum = payload;
    }

    @Action({ commit: 'SET_USER_NUMBER' })
    addUserNumber(n = 5) {
        return this.userNum + n;
    }
}

export default getModule(UserModule);

Finally use it in your Vue component:

import { Vue, Component } from 'vue-property-decorator';

import userModule from '@/store/modules/userModule';

@Component({
    name: 'Todo'
})
export default class Todo extends Vue {
    private get userNum() {
        return userModule.userNum;
    }
    public clickBtn() {
        userModule.addUserNumber(11);
    }
}

I hope this helps!

All 2 comments

Hey there, I came with the following solution by using the preserveState property within the module decorator options. The property value should be true when loading persisted data from local storage (or any other store of choice) and false otherwise, so it uses the initial value since this will be undefined otherwise.

// globals.ts

import SecureLS from 'secure-ls';

export const storageKey = 'vuex';  // the key used by localStorage

export const secureStorage = new SecureLS({ isCompression: false });

const initialStoreContent = secureStorage.get(storageKey); // or localStorage.get(storageKey)
export const initialUnencryptedStorage = initialStoreContent
    ? JSON.parse(initialStoreContent)
    : {};  // parse the localStorage value to an object when it's defined, else set it as an empty object
// store/index.ts

import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';

import { secureStorage } from '@/globals';

Vue.use(Vuex);

// nothing fancy going on here, other than the fact that modules aren't statically inserted into the store object
export default new Vuex.Store({
    plugins: [
        createPersistedState({
            storage: {
                getItem: (key) => secureStorage.get(key),
                setItem: (key, value) => secureStorage.set(key, value),
                removeItem: (key) => secureStorage.remove(key)
            }
        })
    ]
});
// store/modules/userModule.ts

import {
    Module,
    Mutation,
    VuexModule,
    Action,
    getModule
} from 'vuex-module-decorators';

import store from '@/store';

import { initialUnencryptedStorage } from '@/globals';

const name = 'users';

@Module({
    namespaced: true,
    name,
    dynamic: true, // important!
    store, // module is dynamically added to the store here (so after the store was created, instead of during the creation)
    preserveState: Boolean(initialUnencryptedStorage[name]) // preserve state when available from local storage, else don't preserve
})
class UserModule extends VuexModule {
    userNum = 1; // 1 is the initial value when nothing was preserved

    @Mutation
    SET_USER_NUMBER(payload: number) {
        this.userNum = payload;
    }

    @Action({ commit: 'SET_USER_NUMBER' })
    addUserNumber(n = 5) {
        return this.userNum + n;
    }
}

export default getModule(UserModule);

Finally use it in your Vue component:

import { Vue, Component } from 'vue-property-decorator';

import userModule from '@/store/modules/userModule';

@Component({
    name: 'Todo'
})
export default class Todo extends Vue {
    private get userNum() {
        return userModule.userNum;
    }
    public clickBtn() {
        userModule.addUserNumber(11);
    }
}

I hope this helps!

@BasNijhuis thanks for answering!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

abensur picture abensur  路  4Comments

rootsli picture rootsli  路  5Comments

jerometremblay picture jerometremblay  路  6Comments

usu-blog picture usu-blog  路  3Comments

Mrkisha picture Mrkisha  路  3Comments