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

Force reload when clicking on a router-link even if the route doesn't change #1257

Closed
roonie007 opened this issue Dec 28, 2021 · 13 comments
Closed

Comments

@roonie007
Copy link

Version

4.0.12

Reproduction link

codesandbox.io

Steps to reproduce

Simply add a router-link to a view that points to the current page. Then click on that link multiple times, the page or the router-view does not reload or refresh

What is expected?

Refresh or reload the router-view ( same as any HTML a tag )

What is actually happening?

Nothing

@posva
Copy link
Member

posva commented Dec 30, 2021

Duplicate of vuejs/vue-router#974

@posva posva marked this as a duplicate of vuejs/vue-router#974 Dec 30, 2021
@posva posva closed this as completed Dec 30, 2021
@posva
Copy link
Member

posva commented Dec 30, 2021

Note you can pass a random query parameter to force a navigation:

router.push({ query: { _r: Date.now() }})

@roonie007
Copy link
Author

roonie007 commented Dec 30, 2021

Note you can pass a random query parameter to force a navigation:

router.push({ query: { _r: Date.now() }})

Already tried that, but it's a hack and it will just pollute the url, I am looking for a cleaner solution.


Duplicate of vuejs/vue-router#974

I am not sure that's a duplication since it's on a different repo and it's not the same version, more than that it's opened since 2016, i think it's completely ignored by Vue core team.

@roonie007
Copy link
Author

roonie007 commented Feb 22, 2022

An undocumented argument called force can be used to force refresh the page, regardless of whether the URL or path is the same as the current location.

/**
* Triggers the navigation even if the location is the same as the current one
*/
force?: boolean

@posva Perhaps it's worth adding to the documentation?

@posva
Copy link
Member

posva commented Feb 22, 2022

It's not documented for a reason 😉 . Don't rely on it as it could be removed in the future.

@roonie007
Copy link
Author

Let's hope not 😄

@messenjer
Copy link

What do you think about doing this?

await router.push({ path: '/' })
router.go(0)

if delta equals 0, it has the same result as calling location.reload()
https://developer.mozilla.org/en-US/docs/Web/API/History/go

@inca
Copy link

inca commented Aug 19, 2022

Was annoyed by a slightly different use case: fetching data in mounted which wasn't called if you navigate within the same route with different params (e.g. from /user/joe to /user/jane).

Official documentation suggests a pattern of having to watch params in addition to mount, which is a bit too repetitive for my taste, so I finally ended up with <RouterView :key="$route.url"/> which does the job.

If you don't rely on params and different URLs, you can create a global variable, assign a random value in one of the navigation guards, and use that as a key for router view. This way URL doesn't get polluted, and the components are correctly mounted/unmounted on every navigation. You can also customize this behaviour by placing the key on different RouterView levels (in case you have hierarchies or nesting) or by scoping the navigation guards.

@drennvinn
Copy link

drennvinn commented Feb 25, 2023

many thanks @inca 🙏
I was pulling my hair out with the same problem and I didn't think about your solution. this totally solves my problem

Copy link
Member

posva commented Feb 25, 2023

BTW, you don’t need the repetition: using one watch with immediate true is enough (no key on router view)
This is more performant than using a key

@inca
Copy link

inca commented Feb 26, 2023

Interesting. So, what I'm about to say is probably very controversial in Vue community (and kind of off topic), so sorry in advance. IMO/YMMV implied everywhere.

But here goes:

  1. I tend to stay away from watch, and not because of performance problems (it's as performant as other Vue's reactive stuff like computed props and template expressions), but because it breaks the declarativeness of the view layer of the application. I.e. instead of thinking "here's my data, I expect it (and all its deps) to be rendered" you start thinking "when data changes, do something" which is, in my opinion, a slippery path to causality issues and ultimately a lot of 🍝 and debugging. (In fact I've just checked, I've built very big and very dynamic applications and managed to not use watch not even once, and this is something I recommend to not do to the teammates as well.)

  2. I don't really care that much about DOM reusing on router changes. Unless you're doing something really DOM-heavy, you (and, more importantly, your users) won't notice a performance impact of remounting anyway. In this case it also comes at the expense of DX (because as mentioned above, I don't really like thinking in watch terms). The mere fact that Vue Router doesn't have an option to key the RouterView by the props it injects makes me really sad (and occasionally want to build a plugin or similar) — because keying them manually is also tedious and somewhat error prone if you have complex route hierarchy.

I guess the justification for my case is that I only have 3 level nesting, and re-mounting matters only on the last level. In my head even though it's a hack it's still applied only on a couple of layouts (as opposed to every route component) and therefore is much better localized than watch (which is also a hack to be frank).

@carbdias
Copy link

How to do this and keep query parameters?

@edmidev
Copy link

edmidev commented Apr 23, 2024

The simplest solution is to add a :key attribute to :

// Vuejs 2
<router-view :key="$route.fullPath"></router-view>

// Vuejs 3
<router-view :key="route.fullPath"></router-view>

<script>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>

This is because Vue Router does not notice any change if the same component is being addressed. With the key, any change to the path will trigger a reload of the component with the new data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants