How to solve Avoided redundant navigation to current location error in vue?

I don't think suppressing all errors from router is good practice, I made just picks of certain errors, like this:

router.push(route).catch(err => {
    // Ignore the vuex err regarding  navigating to the page they are already on.
    if (
      err.name !== 'NavigationDuplicated' &&
      !err.message.includes('Avoided redundant navigation to current location')
    ) {
      // But print any other errors to the console
      logError(err);
    }
  });

As I remember well, you can use catch clause after this.$router.push. Then it will look like:

this.$router.push("/admin").catch(()=>{});

This allows you to only avoid the error displaying, because browser thinks the exception was handled.


Just to make this complete you can also compare the from and to route fullPaths and compare them against each other which seems to me a simple, valid and reusable solution.

Here is an example in a component method:

 move(params){
    // get comparable fullPaths
    let from  = this.$route.fullPath
    let to    = this.$router.resolve(params).route.fullPath

    if(from === to) { 
        // handle any error due the redundant navigation here
        // or handle any other param modification and route afterwards
        return 
    }

    // route as expected
    this.$router.push(params)
}

If you wanna use that you just put your route params in it like this.move({ name: 'something' }). This is the easiest way to handle the duplicate route without running into try catch syntax. And also you can have that method exported in Vue.prorotype.$move = ... which will work across the whole application.


Maybe this is happening because your are trying to route to the existing $route.matched.path.

For original-poster

You may want to prevent the error by preventing a route to the same path:

if (this.$route.path != '/admin') {
    this.$router.push("/admin");
}

Generic solutions

You could create a method to check for this if you are sending dynamic routes, using one of several options

  1. Easy: Ignore the error
  2. Hard: Compare the $route.matched against the desired route

1. Ignore the error

You can catch the NavigationDuplicated exception and ignore it.

pushRouteTo(route) {
    try {
        this.$router.push(route);
    } catch (error) {
       if (!(error instanceof NavigationDuplicated)) {
           throw error;
       }
    }
}

Although this is much simpler, it bothers me because it generates an exception.

2. Compare the $route.matched against the desired route

You can compare the $route.matched against the desired route

pushRouteTo(route) {
    // if sending path:
    if (typeof(route) == "string") {
        if (this.$route.path != route) {
            this.$router.push(route);
        }
    } else { // if sending a {name: '', ...}
        if (this.$route.name == route.name) {
            if ('params' in route) {
                let routesMatched = true;
                for (key in this.$route.params) {
                    const value = this.$route.params[key];
                    if (value == null || value == undefined) {
                        if (key in route.params) {
                            if (route.params[key] != undefined && route.params[key] != null) {
                                routesMatched = false;
                                break;
                            }
                        }
                    } else {
                        if (key in route.params) {
                            if (routes.params[key] != value) {
                                routesMatched = false;
                                break
                            }
                        } else {
                            routesMatched = false;
                            break

                        }
                    }
                    if (!routesMatched) {
                        this.$router.push(route);
                    }
                }
            } else {
                if (Object.keys(this.$route.params).length != 0) {
                    this.$router.push(route);
                }
            }
        }
    }
}

This is obviously a lot longer but doesn't throw an error. Choose your poison.

Runnable demo

You can try both implementations in this demo:

const App = {
  methods: {
    goToPageCatchException(route) {
      try {
        this.$router.push(route)
      } catch (error) {
        if (!(error instanceof NavigationDuplicated)) {
          throw error;
        }
      }
    },
    goToPageMatch(route) {
    if (typeof(route) == "string") {
        if (this.$route.path != route) {
            this.$router.push(route);
        }
    } else { // if sending a {name: '', ...}
        if (this.$route.name == route.name) {
            if ('params' in route) {
                let routesMatched = true;
                for (key in this.$route.params) {
                    const value = this.$route.params[key];
                    if (value == null || value == undefined) {
                        if (key in route.params) {
                            if (route.params[key] != undefined && route.params[key] != null) {
                                routesMatched = false;
                                break;
                            }
                        }
                    } else {
                        if (key in route.params) {
                            if (routes.params[key] != value) {
                                routesMatched = false;
                                break
                            }
                        } else {
                            routesMatched = false;
                            break

                        }
                    }
                    if (!routesMatched) {
                        this.$router.push(route);
                    }
                }
            } else {
                if (Object.keys(this.$route.params).length != 0) {
                    this.$router.push(route);
                }
            }
        } else {
          this.$router.push(route);
        }
    }
    },
  },
  template: `
  <div>
    <nav class="navbar bg-light">
          <a href="#" @click.prevent="goToPageCatchException({name:'page1'})">Catch Exception</a>
          <a href="#" @click.prevent="goToPageMatch({name:'page2'})">Match Route</a>
    </nav>
    <router-view></router-view>
  </div>`
}
const Page1 = {template: `
  <div class="container">
    <h1>Catch Exception</h1>
    <p>We used a try/catch to get here</p>
  </div>`
}
const Page2 = {template: `
  <div class="container">
    <h1>Match Route</h1>
    <p>We used a route match to get here</p>
  </div>`
}

const routes = [
  { name: 'page1', path: '/', component: Page1 },
  { name: 'page2', path: '/page2', component: Page2 },
]

const router = new VueRouter({
  routes
})

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.12/vue.min.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app"></div>

Tags:

Vue.Js