Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw Error "NavigationDuplicated" #2872

Closed
tcastelly opened this issue Aug 7, 2019 · 15 comments
Closed

Throw Error "NavigationDuplicated" #2872

tcastelly opened this issue Aug 7, 2019 · 15 comments

Comments

@tcastelly
Copy link

Version

3.1.1

Reproduction link

https://codesandbox.io/s/vue-template-i2d63

Steps to reproduce

Use $router.push to change the "page". If you are using the same page, vue-router throw an Error.

What is expected?

Just nothing, or a warning.

What is actually happening?

An Error has been thrown.


  • To my point of view it's not an error. On a previous version of 'vue-router' no error was threw: https://codesandbox.io/s/vue-template-qvrfr
  • <router-link> does not have the same behavior. There is no error even if you're pushing the current page.
@posva
Copy link
Member

posva commented Aug 7, 2019

This is expected, it's part of the new promise api: before, if no callbacks were supplied to router.push, errors were only sent to the global router error handler. Now, because they return a promise, if the error is not caught, you will see a warning in the console. But the error was always there because trying to navigate to same location as the current one will fail

The behavior with router-link is consistent with how it was working before, no errors are emitted (except globally), it's catching the error by adding a noop callback:

router.push('/location', () => {})

However, the correct solution if you don't care about errors is catching the error:

router.push('/location').catch(err => {})

The last version makes more sense as the Promise api is likely to become the default and the callback version to become deprecated

@posva posva closed this as completed Aug 7, 2019
@shmaram
Copy link

shmaram commented Aug 7, 2019

Hi @posva
In your types folder you can still find the push method as void
https://github.com/vuejs/vue-router/blob/dev/types/router.d.ts

is there a plan to fix this also ?

@posva
Copy link
Member

posva commented Aug 7, 2019

there are two versions of push and replace matching what actually happens

@shmaram
Copy link

shmaram commented Aug 7, 2019

When trying to use the same I get this error, seems like typescript is looks only a the same definition because once I comment out the first
replace (location: RawLocation, onComplete?: Function, onAbort?: ErrorHandler): void;
it works.

before:
image

after:
image

Any idea why?

@TheInvoker
Copy link

pushing a new URL (that is the same path as current page) but the search/hash makes the URL different, doesn't work anymore.

@posva
Copy link
Member

posva commented Aug 8, 2019

@shmaram I will give it a try and push a fix during the day, thanks for letting me know!

@posva
Copy link
Member

posva commented Aug 8, 2019

It's fixed now, I will publish a version during the day

@nchutchind
Copy link

@posva Why does it throw a NavigationDuplicated error when updating params, though? For instance, the router page might be named "User" and have params: { id: userId }. If you call this.$router.push({ name: 'User', params: { id: selectedUserId }}) to change the user being rendered for the current page, should that really count as a NavigationDuplicated error? This is the way it is recommended to change the data for a page, so it seems odd that getting an error is expected behavior.

@posva
Copy link
Member

posva commented Aug 14, 2019

the navigation failure should only happen if the final location is the same as the current one. If it happens with different params, it's a bug so please open a new issue with a boiled down repro

@imtbl
Copy link

imtbl commented Aug 18, 2019

@posva Why does it throw a NavigationDuplicated error when updating params, though? For instance, the router page might be named "User" and have params: { id: userId }. If you call this.$router.push({ name: 'User', params: { id: selectedUserId }}) to change the user being rendered for the current page, should that really count as a NavigationDuplicated error? This is the way it is recommended to change the data for a page, so it seems odd that getting an error is expected behavior.

I can confirm this behavior using this.$router.replace(). Just replacing the query params will cause the NavigationDuplicated error.

E.g., replacing #/search?term=lorem&sort=relevance with #/search?term=lorem&sort=alphabetical via

 this.$router.replace({
  path: '/search',
  query: {
    term: 'lorem',
    sort: 'alphabetical'
  }
})

will cause the NavigationDuplicated error if not catching via

 this.$router.replace({
  path: '/search',
  query: {
    term: 'lorem',
    sort: 'alphabetical'
  }
}).catch(err => {})

It will correctly update the current URL regardless of catching the error or not though.

Is this.$router.replace() not intended to be used for this? I didn't see any other function in the docs for just replacing the query params.

@leolux
Copy link

leolux commented Aug 28, 2019

Is there a shorter way the prevent the console warning than router.push('/location').catch(err => {})?
Is it possible to decorate the push method to handle errors with a noop function?

@Aferz
Copy link

Aferz commented Aug 28, 2019

@posva and what about redirecting inside a route guard?

next({ replace: true, name: 'home' }).catch(err => {})

Is this even possible? Because I'm getting this error caused by a route guard :(

@posva
Copy link
Member

posva commented Aug 29, 2019

@Aferz the catch must be attached to the push/replace methods

@xmsz
Copy link

xmsz commented Oct 16, 2019

@posva Why does it throw a NavigationDuplicated error when updating params, though? For instance, the router page might be named "User" and have params: { id: userId }. If you call this.$router.push({ name: 'User', params: { id: selectedUserId }}) to change the user being rendered for the current page, should that really count as a NavigationDuplicated error? This is the way it is recommended to change the data for a page, so it seems odd that getting an error is expected behavior.

I can confirm this behavior using this.$router.replace(). Just replacing the query params will cause the NavigationDuplicated error.

E.g., replacing #/search?term=lorem&sort=relevance with #/search?term=lorem&sort=alphabetical via

 this.$router.replace({
  path: '/search',
  query: {
    term: 'lorem',
    sort: 'alphabetical'
  }
})

will cause the NavigationDuplicated error if not catching via

 this.$router.replace({
  path: '/search',
  query: {
    term: 'lorem',
    sort: 'alphabetical'
  }
}).catch(err => {})

It will correctly update the current URL regardless of catching the error or not though.

Is this.$router.replace() not intended to be used for this? I didn't see any other function in the docs for just replacing the query params.

Is this fixed?

@posva
Copy link
Member

posva commented Oct 16, 2019

AFAIK the problem didn't appear when I tried. As with any other bug, a boiled reproduction is required. So please open a new issue with it if you can reproduce it. One possibility for the error to happen is to have another push somewhere else or next being called with the same location as the current one. I gave more details about it at #2881 (comment)

Locking this one to redirect to that issue

@vuejs vuejs locked as resolved and limited conversation to collaborators Oct 16, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants