Vue-router: Uncaught TypeError: Cannot read property 'matched' of undefined

Created on 3 Dec 2016  ·  13Comments  ·  Source: vuejs/vue-router

Hi there,

I'm an Angular developer but have recently been checking out Vue. In fact, once I learned about .vue components, I noticed right away they're inspired by Elm which I think is fantastic.

So in these components I'm trying to set up routing:

main.js

import Vue from 'vue';
import VueMaterial from 'vue-material';
import VueRouter from 'vue-router';
import 'vue-material/dist/vue-material.css';
import App from './App.vue';

Vue.use(VueMaterial);
Vue.use(VueRouter);

Vue.material.theme.register('defualt', {
  primary: 'green',
  accent: 'orange',
});

/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App },
});

App.vue

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
import VueRouter from 'vue-router';
import Join from './components/Join.vue';
import Hello from './components/Hello.vue';

const routes = [
  { path: '/', component: Hello },
  { path: '/join', component: Join },
];

const router = new VueRouter(routes);
export default {
  name: 'app',
  router,
  components: { Hello, Join },
};
</script>

I got this from trying to follow the tutorial: http://router.vuejs.org/en/essentials/getting-started.html
The error I'm getting back is pretty obscure.
[Vue warn]: Error when rendering component <app> at App.vue
Uncaught TypeError: Cannot read property 'matched' of undefined

If I try to move the router into main.js the errors disappear but router-view in App.vue never updates (stays blank).

Most helpful comment

This is because Vue expects 'router' instead of 'Router' as the configuration key.

new Vue({ Router }) is actually a shorthand for new Vue({Router: Router})

where what vue expects is new Vue({router: Router})

So, you could change the variable name to 'router'

and use new Vue({ router }) which is equal to new Vue({router: router})

All 13 comments

Hi, thanks for filling this issue. You're passing the wrong arguments to VueRouter constructor, it should be

const routes = [
  { path: '/', component: Hello },
  { path: '/join', component: Join },
];

// fix
const router = new VueRouter({routes});

Take a close look at the tutorial

// 3. Create the router instance and pass the routes option
// You can pass in additional options here, but let's
// keep it simple for now.
const router = new VueRouter({
routes // short for routes: routes
})


Also, the way you created the root instance should have thrown an error about needing a standalone build to compile template, since your root component object contained template option:

new Vue({
  el: '#app',
  // this won't work in runtime-only build which is what you get by default with `import Vue from 'vue'`
  template: '<App/>',  
  components: { App },
});

You can simply change it to

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

@fnlctrl Ahh, and I also needed to move the routing stuff from App.vue to main.js. Great, thank you! Good eye on the messed up VueRouter parameter!

thanks, i also made a mistake putting routing stuffs in my App.vue lol

When I write a router instance, if I write this way ,
```
var Router = new VueRouter({}) ;
new Vue({
Router
})

Then I will receive such a mistake 

TypeError: Cannot read property 'matched' of undefined"

```
If I change the Router to lowercase, it will not be an error ;excuse me, can you tell me the reason??

This is because Vue expects 'router' instead of 'Router' as the configuration key.

new Vue({ Router }) is actually a shorthand for new Vue({Router: Router})

where what vue expects is new Vue({router: Router})

So, you could change the variable name to 'router'

and use new Vue({ router }) which is equal to new Vue({router: router})

APP.vue

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

ROUTERS.js

import FormOne from './components/pageOne.vue'
import FormTwo from './components/pageTwo.vue'

export default [
    { path: '/', component: pageOne},
    { path: '/pageTwo', component: pageTwo }
]

MAIN.js

import Vue from 'vue'
import vueResource from 'vue-resource'
import vueRouter from 'vue-router'
import App from './App'
import Routes from './routes'

Vue.use(vueResource)
Vue.use(vueRouter)

/****************************************/
/********** Router START here **********/
/**************************************/
const router = new vueRouter({
  routes: Routes
}); 

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

I have written this code and this is working fine, you can also try this. :)

@warent @fnlctrl Could you guys help me? I am not sure what I am missing here... I have the same error.

main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import Axios from 'axios'
import Vuex from 'vuex'

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

And my router/index.js

Vue.use(Router)

export const router = new Router({
  routes: [
   {
      path: '/login',
      name: 'Login',
       component: Login
    },
    {
      path: '/dash',
      component: Dashboard,
      children: [
        {
          path: '/home',
          component: Test,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() 
  }
})

@warent @fnlctrl never mind found it. The problem was in the way I was exporting it.

in my router/index.js

const router = new Router({
  routes: [
   {
      path: '/login',
      name: 'Login',
       component: Login
    },
    {
      path: '/dash',
      component: Dashboard,
      children: [
        {
          path: '/home',
          component: Test,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // make sure to always call next()!
  }
})

export default router;

APP.vue

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

ROUTERS.js

import FormOne from './components/pageOne.vue'
import FormTwo from './components/pageTwo.vue'

export default [
  { path: '/', component: pageOne},
  { path: '/pageTwo', component: pageTwo }
]

MAIN.js

import Vue from 'vue'
import vueResource from 'vue-resource'
import vueRouter from 'vue-router'
import App from './App'
import Routes from './routes'

Vue.use(vueResource)
Vue.use(vueRouter)

/****************************************/
/********** Router START here **********/
/**************************************/
const router = new vueRouter({
  routes: Routes
}); 

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

Я написал этот код, и он работает нормально, вы также можете попробовать это. :)

Спасибо!)

APP.vue

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

ROUTERS.js

import FormOne from './components/pageOne.vue'
import FormTwo from './components/pageTwo.vue'

export default [
  { path: '/', component: pageOne},
  { path: '/pageTwo', component: pageTwo }
]

MAIN.js

import Vue from 'vue'
import vueResource from 'vue-resource'
import vueRouter from 'vue-router'
import App from './App'
import Routes from './routes'

Vue.use(vueResource)
Vue.use(vueRouter)

/****************************************/
/********** Router START here **********/
/**************************************/
const router = new vueRouter({
  routes: Routes
}); 

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

I have written this code and this is working fine, you can also try this. :)

Very good example, but there are some small mistakes.

ROUTERS.js

import FormOne from './components/pageOne.vue'
import FormTwo from './components/pageTwo.vue'

// fix
export default [
    {path: '/', component: FormOne},
    {path: '/pageTwo', component: FormTwo}
]

MAIN.js

// fix, and the introduction of vue-resource is unnecessary
import App from './App.vue'
import Routes from './ROUTERS.js'

match bugs

image

image

solution

name must be router

https://stackoverflow.com/a/44618867/5934465

image

OK

image

image


import default module bug

default !== {module name}

I think the document deserves an update. I was using something like vueRouter for the variable name and couldn't figure out why the thing does not work.

https://router.vuejs.org/guide/#javascript

Looking back, it does make sense why the variable must be named that way. But I think the document should make it very clear for beginners.

This is because Vue expects 'router' instead of 'Router' as the configuration key.

new Vue({ Router }) is actually a shorthand for new Vue({Router: Router})

where what vue expects is new Vue({router: Router})

So, you could change the variable name to 'router'

and use new Vue({ router }) which is equal to new Vue({router: router})

:D excelent

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Atinux picture Atinux  ·  3Comments

shinygang picture shinygang  ·  3Comments

gil0mendes picture gil0mendes  ·  3Comments

lbineau picture lbineau  ·  3Comments

posva picture posva  ·  3Comments