Search code examples
vue.jsvuexvuejs3vue-router4

Vue3 - Persisting state with Page refresh


I have just started using Vue3, and am trying to use vuex to manage state. when using Vue2 I would call the store each time the app loads like this:

// mains.js
import VueRouter from "vue-router";
import Vuex from "vuex";
import router from "./routes";

window.Vue = require('vue').default;
Vue.use(VueRouter);
Vue.use(VueMoment);
Vue.use(Vuex);

const store = new Vuex.Store(storeDefinition);

const app = new Vue({
    el: '#app',
    router,
    store,
    components: {
        "index": Index
    },
    async created() {
        this.$store.dispatch("loadStoredState");
        this.$store.dispatch("loadUser");
    },
});

This is my vuex store that defines state, mutations and actions for vuex:

// store.js
import { isLoggedIn, logOut } from "./shared/utils/auth";

export default {
    state: {
        isLoggedIn: false,
        user: {}
    },
    mutations: {
        setUser(state, payload) {
            state.user = payload;
        },
        setLoggedIn(state, payload) {
            state.isLoggedIn = payload;
        }
    },
    actions: {
        loadStoredState(context) {
            context.commit("setLoggedIn", isLoggedIn());
        },
        async loadUser({ commit, dispatch }) {
            if (isLoggedIn()) {
                try {
                    const user = (await axios.get("/user")).data;
                    commit("setUser", user);
                    commit("setLoggedIn", true);
                } catch (error) {
                    dispatch("logout");
                }
            }
        },
        logout({ commit }) {
            commit("setUser", {});
            commit("setLoggedIn", false);
            logOut();
        }
    },
    getters: {}
}

This file manages a cookie for local storage that stores a boolean value for isLoggedIn:

// auth.js
export function isLoggedIn() {
    return localStorage.getItem("isLoggedIn") == 'true';
}

export function logIn() {
    localStorage.setItem("isLoggedIn", true);
}

export function logOut() {
    localStorage.setItem("isLoggedIn", false);
}

But in Vue3 I am creating the main.js file like this:

// mains.js
const { createApp } = require('vue')
import Index from './Index.vue'
import createRouter from './router'
import { createStore } from 'vuex'
import storeDefinition from "./store";

const store = createStore(storeDefinition)

createApp(Index)
    .use(createRouter())
    .use(store)
    .mount('#app')

How can I add the two calls to manage the store to the createApp function?


Solution

  • You can add the created hook to the root component by using the extends option with the component definition:

    // main.js
    import { createApp } from 'vue'
    import Index from './Index.vue'
    import createRouter from './router'
    import { createStore } from 'vuex'
    import storeDefinition from './store'
    
    const store = createStore(storeDefinition)
    
    createApp({
        extends: Index,
        created() {
          this.$store.dispatch('loadStoredState')
          this.$store.dispatch('loadUser')
        },
      })
      .use(createRouter())
      .use(store)
      .mount('#app')
    

    demo