How to save "state" variables to the browser localStorage using Vue.js + Vuex (createStore)
Asked Answered
C

2

2

I am trying to load (using mounted()) and save (with the watch: {...} method) to / from the localStorage.

The two variables i am trying to save to the localstorage are 'categories' and 'locations'.

I just cannot get it triggered for some reason. I have never done this using vue.js/vuex.

all examples I have found use the data: {} object in "regular" components. In my example I am trying to load and save to the state variables. Please help. I have pasted the whole vuex createStore object (project/src/store/index.js):

import { createStore } from 'vuex'

export default createStore({
    state: {
        categories: [ "Food", "Bars", "Parks"],
        locations: [],
    },
    mutations: {
        addCategory(state, newCategory) {
            state.categories.push(newCategory)
        }, 
        removeCategory(state, i) {
            state.categories.splice(i, 1);
        }, 
        saveCategory(state, data) {
            state.categories[data.item] = data.text
        }, 
        addLocation(state, data) {
            state.locations.push(data)
        },
        deleteLocation(state, i) {
            state.locations.splice(i, 1);
        }, 
        saveLocation(state, data) {
            state.locations[data.index].categories = data.item
        },

    },
    watch:{
        categories(newCategories) {
            console.log(newCategories)
            localStorage.categories = JSON.stringify(newCategories)
        }, 
        locations(newLocations) {
            console.log(newLocations)
            localStorage.locations = JSON.stringify(newLocations)
        }
    },
    actions: {
    },
    modules: {
    }, 
    mounted() {
        console.log(localStorage.categories)
        console.log(localStorage.locations)
        if (localStorage.categories) {
            this.categories = JSON.parse(localStorage.categories)
            if (localStorage.locations) 
                this.locations = JSON.parse(localStorage.locations)
        }

    }
})

Edit:

tried:

"state.categories" (newCategories) {
    console.log(newCategories)
    localStorage.categories = JSON.stringify(newCategories)
}, 
"state.locations" (newLocations) {
    console.log(newLocations)
    localStorage.locations = JSON.stringify(newLocations)
}

no errors but doesn't work.

Cathycathyleen answered 24/7, 2021 at 17:3 Comment(0)
C
7

Following the link with the great explanation: https://www.mikestreety.co.uk/blog/vue-js-using-localstorage-with-the-vuex-store/

in my /project/src/main.js file:

store.subscribe( (mutation, state) => {
    localStorage.setItem('categories', JSON.stringify(state.categories));  
    localStorage.setItem('locations', JSON.stringify(state.locations));  
})

in my /project/src/App.vue file I added the following (although I'm pretty sure using "mounted()" will work as well:

beforeMount() {
    this.$store.commit('initialiseVars')
},  

and added a mutation method to /project/src/store/index.js:

initialiseVars(state) {
    if (localStorage.getItem('categories')) {
        state.categories = JSON.parse(localStorage.categories)
        if (localStorage.getItem('locations')) 
            state.locations = JSON.parse(localStorage.locations)
    }
}
Cathycathyleen answered 24/7, 2021 at 18:14 Comment(0)
N
0

I think what you can do is to move the mounted and watch code to your App.vue as that component is always loaded as long as your web-app is loaded.

Also for your watch write it like this:

"state.categories" () {
  // your code here
}
Nels answered 24/7, 2021 at 17:18 Comment(3)
no errors but didn't save anything (or trigger my console.log)Cathycathyleen
I tried doing this in a few variations. my main.js looks like this: createApp(App).use(store).mount('#app'). and in my App.vue file I have the initial Vue. I added watch and mounted there and they do not reach the state.Cathycathyleen
Are you certain your Vuex store is loaded correctly? Trying to console.log "this.state" Does your Vue initialization look like this: new Vue({ store, render: h => h(App) }).$mount("#app");Nels

© 2022 - 2024 — McMap. All rights reserved.