1

for the last 3 days I've been searching all over the net but couldn't find a solution to this issue. When I'm opening my page it gives this error:

ReferenceError: store is not defined
    at app.js:89294
    at iterator (app.js:71515)
    at step (app.js:71241)
    at runQueue (app.js:71249)
    at HTML5History.confirmTransition (app.js:71542)
    at HTML5History.transitionTo (app.js:71429)
    at VueRouter.init (app.js:72129)
    at Vue.beforeCreate (app.js:70598)
    at invokeWithErrorHandling (app.js:76676)
    at callHook (app.js:79027)

I managed to track issue to my router.js file but couldn't fix the issue. I also tried to import my store file into router file but it returned Maximum call stack size exceeded error.

Code

Router.js

import Vue from "vue";
import VueRouter from 'vue-router';
Vue.use(VueRouter);

import pageAbout from './components/About.vue';
import pageHome from './components/Home.vue';
import pageBooks from './components/Books.vue';
import pageChapters from './components/Chapters.vue';
import pageVerses from './components/Verses.vue';

import Dashboard from './components/admin/Dashboard.vue';
import Register from './components/auth/Register.vue';
import Login from './components/auth/Login.vue';

import passportclients from './components/passport/Clients.vue';
import passportauthorizedclients from './components/passport/AuthorizedClients.vue';
import passportpersonalaccesstokens from './components/passport/PersonalAccessTokens.vue';

import adminVerses from './components/admin/verses.vue';
import NotFoundComponent from './components/NotFoundComponent.vue';

const router = new VueRouter({
    mode: "history",
    routes: [
        {
            path: '*',
            name: '404',
            component: NotFoundComponent
        },
        // ADMIN ROUTES
        {
            path: '/dashboard',
            name: 'dashboard',
            component: Dashboard,
            meta: { requiresAuth: true },
            children: [
                {
                    path: '/verses',
                    name: 'adminVerses',
                    component: adminVerses,
                    meta: { requiresAuth: true }
                },
                {
                    path: '/passport-clients',
                    name: 'passport-clients',
                    component: passportclients,
                    meta: { requiresAuth: true }
                },
                {
                    path: '/passport-authorized-clients',
                    name: 'passport-authorized-clients',
                    component: passportauthorizedclients,
                    meta: { requiresAuth: true }
                },
                {
                    path: '/passport-personal-access-tokens',
                    name: 'passport-personal-access-tokens',
                    component: passportpersonalaccesstokens,
                    meta: { requiresAuth: true }
                }
            ]
        },

        // public routes
        {
            path: "/",
            name: 'home',
            component: pageHome
        },
        {
            path: "/about",
            name: 'about',
            component: pageAbout
        },
        {
            path: "/book/:slug",
            name: 'books',
            component: pageBooks
        },
        {
            path: "/book/:book_slug/:slug",
            name: 'chapters',
            component: pageChapters
        },
        {
            path: "/book/:testament_slug/:book_slug/:slug",
            name: 'verses',
            component: pageVerses
        },
        // auth
        {
            path: '/register',
            name: 'register',
            component: Register
        },
        {
            path: '/login',
            name: 'login',
            component: Login
        }
    ]
});

router.afterEach((to, from) => {
    Vue.nextTick(() => {
        document.title = to.pageTitle || 'Bible';
    });
});


router.beforeEach((to, from, next) => {
    var requiresAuth = to.matched.some( record => record.meta.requiresAuth );
    // when route requires auth and there's no current user, reidrect to '/login'
    if(!store.getters.isLoggedIn){
      next({name: 'login'});
    // when we go to login route and are already logged in, we can skip this page
    // so we redirect to the homepage
    } else if (to.path == '/login' && store.getters.isLoggedIn){
      next({name: 'home'});
    // if none of the above matches, we have a normal navigation that should just go through
    // so we call `next()`
    } else {
      next(); // you called `next('/')` which redirected to the homepage over and over again.
    }
});

export default router;

Store.js

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    status: '',
    token: localStorage.getItem('access_token') || '',
    type: localStorage.getItem('token_type') || '',
    user : {}
  },
  mutations: {
    auth_request(state){
        state.status = 'loading'
      },
      auth_success(state, type, token, user){
        state.status = 'success'
        state.token = token
        state.type = type
        state.user = user
      },
      auth_error(state){
        state.status = 'error'
      },
      logout(state){
        state.status = ''
        state.token = ''
        state.type = ''
      },
  },
  actions: {
    login({commit}, user){
        return new Promise((resolve, reject) => {
          commit('auth_request')
          axios({url: '/api/auth/login', data: user, method: 'POST' })
          .then(resp => {
            console.log('login data', resp);
            const token = resp.data.token
            const type = resp.data.token_type
            const user = resp.data.user
            localStorage.setItem('token', token)
            localStorage.setItem('token_type', type)
            axios.defaults.headers.common['Authorization'] =  'Bearer ' + token
            commit('auth_success', token, type, user)
            resolve(resp)
          })
          .catch(err => {
            commit('auth_error')
            localStorage.removeItem('token')
            reject(err)
          })
        })
    },
    register({commit}, user){
        return new Promise((resolve, reject) => {
          commit('auth_request')
          axios({url: 'api/auth/register', data: user, method: 'POST' })
          .then(resp => {
            console.log('register data', resp);
            const token = resp.data.access_token
            const type = resp.data.token_type
            const user = resp.data.user
            localStorage.setItem('access_token', token)
            localStorage.setItem('token_type', type)
            axios.defaults.headers.common['Authorization'] =  'Bearer ' + token
            commit('auth_success', token, type, user)
            resolve(resp)
          })
          .catch(err => {
            commit('auth_error', err)
            localStorage.removeItem('access_token')
            reject(err)
          })
        })
      },
      logout({commit}){
        axios.defaults.headers.common['Authorization'] = 'Bearer ' + this.state.token
        return new Promise((resolve, reject) => {
        axios({url: 'api/auth/logout', method: 'POST' })
          .then(resp => {
            commit('logout')
            localStorage.removeItem('access_token')
            localStorage.removeItem('token_type')
            delete axios.defaults.headers.common['Authorization']
            resolve()
          })
          .catch(err => {
            commit('logout')
            localStorage.removeItem('access_token')
            localStorage.removeItem('token_type')
            delete axios.defaults.headers.common['Authorization']
            reject(err)
          })
        })
      }
  },
  getters: {
    isLoggedIn: state => !!state.token,
    authStatus: state => state.status,
    LoggedUser: state => state.user,
  }
});

App.js

require('./bootstrap');
window.Vue = require('vue');

import Darkmode from 'darkmode-js';
import App from "./components/App";

import 'es6-promise/auto';
import axios from 'axios';
import VueAxios from 'vue-axios';
import VueRouter from 'vue-router';
import router from './router';
import Vuex from 'vuex';
import 'es6-promise/auto';
import store from './store';


// Set Vue globally
window.Vue = Vue
// Set Vue router
Vue.router = router;
Vue.use(VueRouter);
// Set Vue authentication
Vue.use(VueAxios, axios);
Vue.use(Vuex);

const token = localStorage.getItem('access_token')
if (token) {
  axios.defaults.headers.common['Authorization'] = 'Bearer ' + token
}

const app = new Vue({
    el: '#app',
    router,
    store,
    render: (h) => h(App)
});

App.vue (main component)

<script>
    export default {
        data() {
            return {
                user: ''
            }
        },
        computed : {
            isLoggedIn() {
                return this.$store.getters.isLoggedIn
            }
        },
        methods: {
            logout: function () {
                this.$store.dispatch('logout')
                .then(() => {
                    this.$router.push({name: 'home'})
                })
            }
        },
        created: function () {
            this.user = this.$store.state.user
        }
    }
</script>

Question

How to fix this error?

Update

Based on comment suggestion I have to import my store to router.js file and it returns Maximum call stack size exceeded error.

How to fix Maximum call stack size exceeded?

16
  • @JaromandaX the router is not a component. I don't think this.$store is defined on it. Commented Jan 2, 2020 at 1:43
  • @mafortis you should change the title. You know how to solve the not defined issue. Your real issue is the stack overflow. Commented Jan 2, 2020 at 1:43
  • @JaromandaX it returns TypeError: Cannot read property '$store' of undefined Commented Jan 2, 2020 at 1:49
  • @MarkMeyer the title is my error message :) what do you like me to change it to? :D Commented Jan 2, 2020 at 1:50
  • 1
    it's too bad the error message doesnt' have a stack trace you can trace back to a particular line in your code Commented Jan 2, 2020 at 2:03

1 Answer 1

1

Your logic causes an infinite redirection to /login

try the following logic - I think it's right

router.beforeEach((to, from, next) => {
  var requiresAuth = to.matched.some(record => record.meta.requiresAuth);
  if (to.path != '/login' && !store.getters.isLoggedIn) {
    next({
      name: 'login'
    });
  } else if (to.path == '/login' && store.getters.isLoggedIn) {
    next({
      name: 'home'
    });
  } else {
    next();
  }
});

As a bonus, here's what I mean by Promise constructor anti-pattern

axios returns a promise ... no need to wrap it in a new Promise constructor

So, for example, your login function should be written

login({commit}, user){
    commit('auth_request');
    return axios({url: '/api/auth/login', data: user, method: 'POST' })
    .then(resp => {
        console.log('login data', resp);
        const token = resp.data.token;
        const type = resp.data.token_type;
        const user = resp.data.user;
        localStorage.setItem('token', token);
        localStorage.setItem('token_type', type);
        axios.defaults.headers.common['Authorization'] =  'Bearer ' + token;
        commit('auth_success', token, type, user);
        return resp;
    })
    .catch(err => {
        commit('auth_error');
        localStorage.removeItem('token');
        throw err;
    });
}
Sign up to request clarification or add additional context in comments.

8 Comments

that prevent the exceeded error but one i click on links such as login or logout i get uncaught (in promise) error. could it be related to this beforeeach or that's something else? PS in case you want to see i made screen recording of the error loom.com/share/81807ff673e94b688b90d9c97c01c083
ncaught (in promise) error - surely it says more than that - if not, use a browser that gives meaningful errors
I think you already watch the video i shared all i'm getting is Uncaught (in promise) undefined
clearly something in your promise code is attempting to use a property of something that is undefined - have you tried debugging this new problem yourself?
it was duplicated redirect after login, one in my beforeeach and one in my login function. Thanks for the help appreciate it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.