Search code examples
vue.jsvuejs2vuexbootstrap-vuevuex-modules

app.js:81010 [Vue warn]: Error in mounted hook: "ReferenceError: $store is not defined"


I am attempting to refactor my code to use vuex. I am getting 2 errors: app.js:81010 [Vue warn]: Error in mounted hook: "ReferenceError: $store is not defined" and ReferenceError: $store is not defined. I think I imported vuex properly.

My goal is to update my bootstrap-vue data-table with the employee data from my database using vuex.

In the EmployeeDataTable.vue file I have a getEmployees method in methods: {} which I would like it to dispatch the fetchAllEmployees action from employees.js. fetchAllEmployees should grab all of the employees from the database and save the result to the employees.js employees: [] state.

I am now confused and need help getting in the right direction to fix this issue.

I don't know if I needed to show all of this code, but I wanted to show the flow of my components.

Entry point App.js:

import Vue from 'vue';
import store from './store';
import router from './router';
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'

import App from './components/App';


Vue.use(BootstrapVue);
Vue.use(IconsPlugin);

require('./bootstrap');

const app = new Vue({
    el: '#app',

    components: {
        App,
    },

    router,

    store,
});

Vuex Store index.js:

import Vue from 'vue';
import Vuex from 'vuex';
import Employees from './modules/employees';

Vue.use(Vuex);

export default new Vuex.Store({
    modules: {
        Employees,
    }
});

Vuex module employees.js:

const state = {
    employees: [],
    employeesStatus: null,
};

const getters = {
    allEmployees: (state) => state.employees
};

const actions = {
    fetchAllEmployees({commit, state}) {
        commit('setPostsStatus', 'loading');

        axios.get('/api/employees')
            .then(res => {
                commit('employees', res.data);
                commit('employeesStatus', 'success');
            })
            .catch(error => {
                commit('setEmployeesStatus', 'error');
            });
    },
};

const mutations = {
    setEmployees(state, employees) {
        state.employees = employees;
    },
    setEmployeesStatus(state, status) {
        state.employeesStatus = status;
    } 
};

export default {
    state, getters, actions, mutations,
};

App.vue:

<template>
    <div>
        <router-view></router-view>
    </div>
</template>

<script>
    export default {
        name: "App"
    }
</script>

<style scoped>

</style>

DashBoard.vue:

<template>
    <div>
        <b-container>
            <b-row>
                <b-col class="col-12 col-sm-12 col-md-5 col-lg-4 col-xl-4">
                    <b-list-group class="d-flex horiz mx-5">
                        <b-list-group-item class="list-group-item-padding">
                            <b-link v-on:click="component='home'">
                                <i class="fas fa-home"></i>
                                <span class="custom-sm-d-none">Home</span>
                            </b-link>
                        </b-list-group-item>
                        <b-list-group-item class="list-group-item-padding">
                            <b-link v-on:click="component = 'projects'">
                                <i class="fas fa-project-diagram"></i>
                                <span class="custom-sm-d-none">Projects</span>
                            </b-link>
                        </b-list-group-item>
                        <b-list-group-item class="list-group-item-padding">
                            <b-link v-on:click="component = 'employees'">
                                <i class="fas fa-user"></i>
                                <span class="custom-sm-d-none">Employees</span>
                            </b-link>
                        </b-list-group-item>
                        <b-list-group-item class="list-group-item-padding">
                            <b-link v-on:click="component = 'customers'">
                                <i class="fas fa-users"></i>
                                <span class="custom-sm-d-none">Customers</span>
                            </b-link>
                        </b-list-group-item>
                        <b-list-group-item class="list-group-item-padding">
                            <b-link v-on:click="component = 'batch-create-material-list'">
                                <i class="fas fa-toolbox"></i>
                                <span class="custom-sm-d-none">Materials</span>
                            </b-link>
                        </b-list-group-item>
                        <b-list-group-item class="">
                            <b-link v-on:click="component = 'product-list'">
                                <i class="fas fa-clipboard-list icon-5x"></i>
                                <span class="custom-sm-d-none">Tasks</span>
                            </b-link>
                        </b-list-group-item>
                    </b-list-group>
                </b-col>
                <b-col class="col-12 col-md-7 col-lg-8 col-xl-8">
                    <keep-alive>
                        <component v-bind:is="component"></component>
                    </keep-alive>
                </b-col>
            </b-row>
        </b-container>
    </div>       
</template>

<script>
import Home from '../../components/admin/Home';
import Projects from '../../components/admin/Projects';
import Employees from '../../components/admin/Employees';
import Customers from '../../components/admin/Customers'
import ProductList from '../../components/admin/ProductList';
import CreateProductAndCategory from '../../components/admin/CreateProductAndCategory';


export default {
    name: 'Dashboard',

    components: {
        'home': Home,
        'projects': Projects,
        'employees': Employees,
        'customers': Customers,
        'product-list': ProductList,
        'batch-create-material-list': CreateProductAndCategory,

    },

    data() {
        return {
            component: 'product-list',
        }
    },


}
</script>

<style scoped>
/* small screen  below 768px width */
@media only screen and (max-width : 691px) { 
    .custom-sm-d-none{display:none;}

    .horiz {
        flex-direction: row;
        justify-content: space-evenly;
        padding-bottom: 10px;
    }

    .list-group-item-padding {
        margin-right: 10px;
    }
}
</style>

Component Employees.vue:

<template>
    <div>
        <EmployeeDataTable/>
        <CreateEmployee />
    </div>
</template>

<script>
import EmployeeDataTable from "./EmployeeDataTable"
import CreateEmployee from "./CreateEmployee"

export default {
    components: {
      EmployeeDataTable,
      CreateEmployee,  
    },

}
</script>

<style scoped>

</style>

Component EmployeeDataTable.vue:

<template>
    <div class="overflow-auto pb-3" style="background: white; ">
        <b-card
        header="Employees"
        header-tag="header"
        >
            <b-pagination
            v-model="currentPage"
            :total-rows="rows"
            :per-page="perPage"
            aria-controls="my-table"
            ></b-pagination>

            <p class="mt-3">Current Page: {{ currentPage }}</p>

            <b-table
            id="employee-table"
            ref="employee-table"
            :items="items"
            :per-page="perPage"
            :current-page="currentPage"
            small
            ></b-table>
        </b-card>
    </div>
</template>

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

  export default {
    name: "EmployeeDataTable",

    data() {
      return {
        perPage: 3,
        currentPage: 1,
        items: [],
      }
    },
    computed: {
      ...mapGetters(['allEmployees']),

      rows() {
        return this.items.length
      }
    },
    methods: {
        getEmployees() {
          $store.dispatch('fetchAllEmployees').then(() => {
            console.log('Dispatched getEmployees method!');
          });
        }
    },
    mounted() {
        this.getEmployees();
    }
  }
</script>

Solution

  • Use this.$store instead of $store in the component. Change your API call to:

    axios.get('/api/employees')
      .then(res => {
        commit('setEmployees', res.data);
        commit('setEmployeesStatus', 'success');
      })
      .catch(error => {
        commit('setEmployeesStatus', 'error');
      });
    

    The difference now is that you're calling the mutation names. In your success commit, you had the state names instead of the mutations.

    One common convention people use in Vuex is to name mutations in all caps, and it might help in a situation like this (by making it more obvious if you used a state name instead). You'd rename them to SET_EMPLOYEES and SET_EMPLOYEES_STATUS.