vuex-persistedstate not Working in NuxtJS

Created on 28 Mar 2018  路  9Comments  路  Source: robinvdvleuten/vuex-persistedstate

please validate the following configuration which I am trying to use with NuxtJS where SSR is enabled.
On browser refreshes, the values are not retained in the text boxes.

0) package.json

"dependencies": {
    "js-cookie": "^2.2.0",
    "nuxt": "^1.0.0",
    "vue": "^2.5.16",
    "vuex-persistedstate": "^2.5.1"
  },
  "devDependencies": {
    "cross-env": "^5.0.1"
  }

1) nuxt.config.js

plugins: [{ src: '~/plugins/localStorage.js', ssr: true }],

2) plugins/localStorage.js

import createPersistedState from 'vuex-persistedstate'
import * as Cookies from 'js-cookie'

export default ({store}) => {
  createPersistedState({
      key: 'vuex',
      paths: [],
      storage: {
              getItem: key => Cookies.get(key),
              setItem: (key, value) => Cookies.set(key, value, { expires: 3, secure: true }),
              removeItem: key => Cookies.remove(key)
            }
  })(store)
}

3) store/index.js

import Vuex from  'vuex';

const store = ()  =>  {
return new Vuex.Store({
    state: {
        count: 0,
        firstName:'',
        lastName:'',
        email:'',
        ssn:'',
        phoneNumber:'',
        addressLine1:'',
        addressLine2:'',
        city:'',
        state1:'',
        zip:''
    },
    getters: {
        firstName(state) {
          return state.firstName;
        },
        lastName(state) {
            return state.lastName;
          },
        email(state) {
            return state.email;
        },
        ssn(state) {
            return state.ssn;
        },
        phoneNumber(state) {
            return state.phoneNumber;
        },
        addressLine1(state) {
            return state.addressLine1;
        },
        addressLine2(state) {
            return state.addressLine2;
        },
        city(state) {
            return state.city;
        },
        state1(state) {
            return state.state1;
        },
        zip(state) {
            return state.zip;
        }
    },
    mutations: {
        updateFirstName(state, firstName){
            state.firstName = firstName ;    
        },
        updateCount(state, increment) {
            state.count += increment;
        },
        updateLastName(state, lastName){
            state.lastName = lastName ;    
        },
        updateEmail(state, email){
            state.email = email ;    
        },
        updateSSN(state,ssn) {
            state.ssn = ssn;
        },
        updatePhoneNumber(state,phoneNumber) {
            state.phoneNumber = phoneNumber;
        },
        updateAddressLine1(state,addressLine1) {
            state.addressLine1 = addressLine1;
        },
        updateAddressLine2(state,addressLine2) {
            state.addressLine2 = addressLine2;
        },
        updateCity(state,city) {
            state.city = city;
        },
        updateState(state,state1) {
            state.state1 = state1;
        },
        updateZip(state,zip) {
            state.zip = zip;
        }
    }
})
}

export default store

4) pages/step1/index.vue

<template>
    <div>
        <form >
            <div>
                <label for="name">FirstName:</label>
                <input type="text" :value="firstName" @input="updateFirstName" id="firstName">
            </div>
            <div>
                <label for="mail">LastName:</label>
                <input type="text" :value="lastName" @input="updateLastName" id="lastName">
            </div>
            <div>
                <label for="msg">Email:</label>
                <input type="email" :value="email" @input="updateEmail" id="email">
            </div>
            <div class="button">
                <button type="submit">Save</button>
                 <router-link to="/step2" tag="button">Next</router-link>
            </div>
        </form>
    </div>  
</template>

<script>
import {mapGetters} from 'vuex';
export default {

  computed: 
      mapGetters([
        'firstName',
        'lastName',
        'email'
      ]),
    // firstName() {
    //   return this.$store.getters.firstName;
    // },
    // lastName() {
    //   return this.$store.getters.lastName;
    // },
    // email() {
    //   return this.$store.getters.email;
    // }

  methods: {
    updateFirstName(e) {
        this.$store.commit('updateFirstName', e.target.value);
    },
    updateLastName(e) {
        this.$store.commit('updateLastName', e.target.value);
    }, 
    updateEmail(e) {
        this.$store.commit('updateEmail', e.target.value);
    }
  }

}
</script>
question

Most helpful comment

import createPersistedState from 'vuex-persistedstate';
import * as Cookies from "js-cookie";

let cookieStorage = {
  getItem: function(key) {
    return Cookies.getJSON(key);
  },
  setItem: function(key, value) {
    return Cookies.set(key, value, {expires: 3, secure: false});
  },
  removeItem: function(key) {
    return Cookies.remove(key);
  }
};

export default (context) => {
  createPersistedState({
    storage: cookieStorage,
    getState: cookieStorage.getItem,
    setState: cookieStorage.setItem
  })(context.store);
};


plugins: [
    { src: '~/plugins/localStorage.js', ssr: false }
]

It works for me.

All 9 comments

I see that you are using the secure option when setting cookies. Do you run your code with HTTPS?

Thank You.. it worked.

Is there a way I could configure my vuex-persisted-state to use window.sessionStorage instead of cookie based local storage especially in a nuxtjs SSR enabled application...? Won't the window is undefined while the page is server rendered? Please shed some light on how to achieve session storage in a nuxtjs server side rendered application..

@pkganthali

//  ~/plugins/vuex-persistedstate.js
import createPersistedState from 'vuex-persistedstate'

export default ({ store }) => {
    createPersistedState({
        // other options...
        storage: sessionStorage,
  })(store)
}

And in your nuxt.config.js file:

// nuxt.config.js

plugins: [
    // other plugins...
    { src: '~/plugins/vuex-persistedstate.js', ssr: false },
]

The ssr: false part is the important one, as it is explained in the Readme.

Although that was not related with the original question. Can we close the issue now? Thank you.

@gangsthub

import createPersistedState from 'vuex-persistedstate'

export default ({store}) => {
  createPersistedState({
      key: 'vuex',
      paths: [],
      storage: {
              getItem: key => sessionStorage.get(key),
              setItem: (key, value) => sessionStorage.set(key, value),
              removeItem: key => {
                  sessionStorage.remove(key);
              }  
            }
  })(store)
}

It is not working, I have given ssr : false. Its complaining Invalid storage instance given. I tried giving window.sessionStorage too

You'll receive that error when the plugin is unable to write to the provided storage instance, see https://github.com/robinvdvleuten/vuex-persistedstate/blob/master/index.js#L52. As it is unrelated to your initial question and not an issue, I am gonna close this.

import createPersistedState from 'vuex-persistedstate';
import * as Cookies from "js-cookie";

let cookieStorage = {
  getItem: function(key) {
    return Cookies.getJSON(key);
  },
  setItem: function(key, value) {
    return Cookies.set(key, value, {expires: 3, secure: false});
  },
  removeItem: function(key) {
    return Cookies.remove(key);
  }
};

export default (context) => {
  createPersistedState({
    storage: cookieStorage,
    getState: cookieStorage.getItem,
    setState: cookieStorage.setItem
  })(context.store);
};


plugins: [
    { src: '~/plugins/localStorage.js', ssr: false }
]

It works for me.

An another problem can be with the data size when you use cookies for that. There is a limit of 4096b. So when you're trying to set more data than cookie can get, the browser (at least Google Chrome in my case) will silently ignore your wish.

I faced such problem and I solved it by using state modules and saving each module state in separated cookie.

I used https://www.npmjs.com/package/cookie-universal-nuxt

Here is my code example:

  • plugins/persistedstate.js
import createPersistedState from 'vuex-persistedstate';

export default ({store, app}) => {
    createPersistedState({
        storage: {
            getItem: (vuexKey) => {
                const vuex = {};
                const cookies = app.$cookies.getAll();
                for (const subKey of Object.keys(cookies)) {
                    if (subKey.split('_')[0] === vuexKey) {
                        const modKey = subKey.replace(vuexKey + '_', '');
                        vuex[modKey] = cookies[subKey];
                    }
                }
                return vuex;
            },
            setItem: (vuexKey, value) => {
                const json = JSON.parse(value);
                for (const k of Object.keys(json)) {
                    const subKey = vuexKey + '_' + k;
                    app.$cookies.set(subKey, json[k], {path: '/', maxAge: 60 * 60 * 24 * 7, secure: false});
                }
                return true;
            },
            removeItem: (vuexKey) => {
                const cookies = app.$cookies.getAll();
                for (const subKey of Object.keys(cookies)) {
                    if (subKey.split('_')[0] === vuexKey) {
                        app.$cookies.remove(subKey);
                    }
                }
                return true;
            }
        }
    })(store)
}
  • store/index.js
export const actions = {

    async nuxtServerInit({commit}, { req }) {
        const vuexKey = 'vuex';
        try {
            const cookies = this.$cookies.getAll();
            if (!!cookies[vuexKey+'_auth']) commit('auth/setUserInfo', cookies[vuexKey+'_auth']);
            if (!!cookies[vuexKey+'_module2']) commit('cart-items/setItems', cookies[vuexKey+'_module2'].items);

            // another stuff ...

        } catch (e) {
            commit("something", []);
            console.log("STATE ERROR: ", e)
        }
    }
};

It's a bit dirty code but I hope you've got an idea.

@adamasantares this saves me thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chadwtaylor picture chadwtaylor  路  5Comments

irrg picture irrg  路  6Comments

umardraz picture umardraz  路  3Comments

Mrkisha picture Mrkisha  路  3Comments

uxinkc picture uxinkc  路  3Comments