Sometimes we need our VueJS Web App to persist some information in browser local storage. It could be local settings, account info or some tokens. We definitely don’t want to lose them once the page is refreshed.
In this quick example, I’ll show how to use vuex and vuex-persistedstate to make the magic happen.
Let’s start with required libraries!
Assuming you already generated your VueJS project, we will need an extra dependency, which is a vuex
state management library:
npm install --save vuex
Our application at start should look something like this:
├── index.html
├── main.js
├── components
│ ├── App.vue
To start creating a store, we need to create a store
directory on the same level as components
and main.js
.
Then, inside newly-created store
directory we will create index.js
- which will be a reference entry point for our store configuration.
Inside store/index.js
file we are going to create a store and export it to be used by our application:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
});
export default store
That’s it! We created our store!
Now your project should be like this:
├── index.html
├── main.js
├── components
│ ├── App.vue
└── store
├── index.js
Next step is to make our store available globally, for this purpose it is enough to reference it inside main.js
file just like this:
import Vue from 'vue'
import App from './components/App'
import store from './store';
Vue.config.productionTip = false
new Vue({
el: '#app',
store,
template: '<App/>',
components: { App }
})
Amazing! But what about actual logic?
Now let’s imagine we need to store some User ID information. For our basic functionality we will have login (which will set User ID) and logout (which will set User ID to null).
Firstly, let’s create modules
directory in our store
folder. The main logic behind modules
is to decouple store according to some context. Otherwise we can end up with a single file and super-mega-big unmanageable store.
Inside modules
now it is a time to create account.js
with all required logic:
const state = {
userId: null
};
const mutations = {
logout(state) {
state.userId = null;
},
login(state, userId) {
state.userId = userId;
}
};
export default {
state,
mutations
}
So, what's happening here?
Firstly, we declare our store property with a single variable, which is userId
. By default it is null
.
Next, we have something which is called mutations
with two simple functions: login
and logout
. Main idea behind vuex
is that we do not directly mutate a store, but commit our changes. Basically, these functions will be call on commit only.
Our project should look like this:
├── index.html
├── main.js
├── components
│ ├── App.vue
└── store
├── index.js
├── modules
├── account.js
But how would store know about our newly-created account.js
? We need to declare it!
Inside our store/index.js
let's do it:
import Vue from 'vue'
import Vuex from 'vuex'
import account from './modules/account'
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
account,
}
});
export default store
As you can see, we simply imported our account.js
and referenced it inside modules for the store. Easy!
It is a time to try our amazing store!
Inside our App.vue
:
<template>
<div>
<div>{{this.userId}}</div>
<button @click="login()">Login as Nick</button>
<button @click="logout()">Logout</button>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'app',
computed: mapState({
userId: state => state.account.userId
}),
methods: {
login() {
this.$store.commit('login', 'Nick')
},
logout() {
this.$store.commit('logout')
}
},
}
</script>
In this example, we are using mapState
from vuex
inside computed
vue property which allows us to translate global state into our local store properties. If anything changed in global store, it will be also changed in our component properties. As a result we can simply use this.userId
, which is directly mapped from global store of our account
context.
Next, we are using two methods: login
and logout
. As you can see now, to modify our store we commit a change, specified earlier in account mutations
property.
Awesome! We made it!
But... if you reload a page...
Yes, unfortunately it doesn't persist.
If you open Application/Local Storage
in Chrome, there will be no trace of our userId
.
But there is a solution called vuex-persistedstate!
Let's install a plugin which allows our state to persist on local storage:
npm install --save vuex-persistedstate
For our vanilla configuration it is enough to reference it as a plugin inside store/index.js
as follows:
import Vue from 'vue'
import Vuex from 'vuex'
import account from './modules/account'
import createPersistedState from "vuex-persistedstate";
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
account,
},
plugins: [createPersistedState()]
});
export default store
Now if you reload a page once logged in - it will be persisted in local storage on your browser!
Good job, you made it! Now your app can truly store things!
For more references, go to here => https://vuex.vuejs.org/
Top comments (8)
How can i do to only persist an state module?
try this: github.com/titan-suite/ide/blob/ma...
Thanks, this was helpful!
Thanks! 👌👌👌
Alternative: npmjs.com/package/persisted-state-...
Thanks 🥳 exactly the answer I've been searching for a week 😭😂
Great tutorial! :)
Great simple explanation of Vuex and how to solve that pesky “lose-store-on-reload” problem. Thanks!!!