1
votes

I'm using a project with Vue, Vuetify, Vue-Router, and Vuex. The intent was to create a basic layout with a sidebar in a more module approach to dabble in scalability with Vue. So I created a folder called Store, which has a modules folder. So my index file within the store folder is as follows:

import Vue from 'vue';
import Vuex from 'vuex';
import global from './Modules/Global';

Vue.use(Vuex);

export default new Vuex.Store({
     modules: {
          site: global
     }
});

The module is broken down into a single file with actions, getters, mutations, and state.

const actions = {
    sidebarState: ({ commit }, status) => {
        commit('openOrCloseSidebar', status);
    }
}

const mutations = {
    openOrCloseMenu: (status) => {
        if (status !== true)
            return state.sidebar = true;

        return state.sidebar = false;
    }
};

const getters = {

};

const state = {
    sidebar: true
};

export default {
    namespaced: true,
    actions,
    mutations,
    getters,
    state
};

I invoke the Vue instance as follows.

import Vue from 'vue/dist/vue';
import Vuetify from 'vuetify';
import Axios from 'axios';

import application from './Template/Application.vue';

import router from './Router';
import store from './Store';
import { sync } from 'vuex-router-sync';

Vue.use(Vuetify);
Vue.use(router);
Vue.use(store);

sync(store, router);

var vue = new Vue({
    el: '#application',
    template: '<application></application>',
    components: {
        application
    },

    router: router,
    store: store
});

However, when I call this.$store.global.state.sidebar or this.$store.state.sidebar Vue is unable to find my property. I receive the error:

Cannot read property global of undefined.

The error also references state, but I believe since I'm using namespace the syntax should mirror above. Where I attempt to call that is here.

<template>
    <v-container>
        <application_sidebar :my-prop="menu"></application_sidebar>
        <application_navigation :my-prop="menu"></application_navigation>        
    </v-container>
</template>

<script type="text/javascript">
    import application_navigation from './Navigation.vue'
    import application_sidebar from './Sidebar.vue';
    import { mapState } from 'vuex';

    export default ({
        components: {
            application_navigation,
            application_sidebar
        },

        data: {
            menu: this.$store.global.state.sidebar
        }
    });
</script>

I'm trying to access my state and learn how to correctly emit, so in the navigation component I can emit upward so the value is reflected to move the sidebar open or close.

Any help would be terrific, I'm quite new to Vue.

2
Afaik you need to pass the configuration to your store in your main.js. Also Vue.use(Vuex); should be in your main.js - connexo
@connexo Aren't I doing that with the Vue.use(store) that calls it? - Greg

2 Answers

4
votes

I think the main problem is your path to your module state is meant to be this.$store.state.site.

The recommended method is to use computed properties. For example

computed: {
  menu() {
    return this.$store.state.site.sidebar
  }
}

You can also use the mapState helper

import { mapState } from 'vuex'

export default {
  computed: mapState({ menu: state => state.site.sidebar })
}
2
votes

The this variable does not reference the Vue instance when you are trying to access the store via this.$store.

The data object needs to be a method that returns an object.

data() {
  return { menu: this.$store.state.site.sidebar };
}

However, by retrieving the value from the store's state object the data method like this, you are only setting the value of the menu data property when the Vue instance initializes. The value of menu will not update in response to changes to the value in the store's state.

If you need the menu value to be reflective of the state object throughout the life of the Vue instance, then you'd need to use a computed property or mapState, as suggested in @Phil's answer.