-
-
Notifications
You must be signed in to change notification settings - Fork 5k
route change should not be changing state until the previous component has been unmounted #3393
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
Comments
Since the component gets unmounted at the same time the route changes, computed properties are not computed again when navigating away from a route. Unfortunately what you are proposing is not possible because the route change is what triggers the change of the component rendered by router view |
@posva - i think you misunderstood me - the properties are being recomputed and watchers are re-triggered, and that's the exact problem. |
I've also just run into this. @tstriker Did you find a resolution? |
No proper resolution downstream. I've been using this workaround where it's needed - wherever i'm depending on the state params i'm checking if we're still in the same state. Stuff like this:
I believe the proper solution is still in vue-router as vue router is the one in control of state changes - since it is logically possible it is not technically impossible, so one might hope @posva could take another look as this is not the case with other non-vue routers. |
@tstriker Thanks! That's what I started doing as well. I suspect I'll have a lot of these to fix after the transition to v4... |
update on this - found a more generic way:
then in the component code can do
the proper fix still would be the destroying of the to-be-unmunted component, of course |
I'm facing this issue too. Is there any plan to fix it? Edit: found the pattern. If I create a watcher for the computed value from {
computed: {
id() {
return parseInt(this.$route.params.slug)
}
},
watch: {
id: {
async handler(val) {
// do something, eg fetch data
}
}
}
} |
I don't want to see log '1' when leaving this component, but currently I'm seeing '1' |
For Vue 3.2 users. |
use watch(() => route.params.id, id => load(id), { immediate: true, flush: 'post' }); |
@posva I think this is still an issue and is still happening in the latest version.
This is not the behavior I am getting (ie computed values on page A still get updated moment before the router switches to page B). Can you confirm? |
In our project we have this code const project = computed(() => propertiesStore.getProjectByQuery({
spaceQuery: { slug: route.params.spaceSlug },
projectQuery: { slug: route.params.projectSlug },
})); And then we watch this value to fetch data but, when we leave the page project.value changes and watcher gets triggered. watch(project,getData); For a workaround we currently use this: export function watchUntilRouteLeave(source, callback, options) {
const stop = watch(source, callback, options);
onBeforeRouteLeave(stop);
return stop;
} watchUntilRouteLeave(project, getData); onBeforeRouteLeave is triggered before |
I ran into this while migrating from vue 2 to vue 3. My current hack is: function useRouteParamDirect(name: string): Ref<string> {
const route = useRoute()
return computed(() => {
const maybe = route.params[name]
if (!maybe) {
throw new Error(`Missing param: ${name}`)
}
return String(maybe)
})
}
export function useRouteParam(name: string): Ref<string> {
const actual = useRouteParamDirect(name)
const validChanges = shallowRef<string>()
watchEffect(() => (validChanges.value = actual.value), {
flush: 'post',
})
return computed(() => validChanges.value || actual.value)
} So my components can just do <script setup lang="ts">
import { useRouteParam } from '@/my-util'
const id = useRouteParam('id')
</script> without having to deal with Surely there's a better way... |
This was reported in 2020, closed immediately, and not reopened after it's clear that it's still an issue for many people. I'm facing the same issue in my migration to Vue 3, and I guess I'm going to have to do the monkey-patching as well. Can we get an update on this, please? |
@lucastraba if you have the time and energy, you could re-file the bug here https://github.com/vuejs/router/issues you'll need to create a reproducible code as it seems to keep falling on deaf ears (my most recent attempt at reviving the bug from last year: vuejs/router#1590 (comment)) |
AFAIK this is not a problem in Vue router 4. There have been other big reports and they have been addressed, in router and core. One of them require watchers to use a flush post, so you might as well try that. If after giving these other issues a try you can still reproduce the problem, open a new issue but with a reproduction so I can take a look |
Uh oh!
There was an error while loading. Please reload this page.
What problem does this feature solve?
When navigating between routes, the changes to state happen before the previous component has been unmounted.
This results in recalculation of any computed properties that rely on the state, even though we'll remove this component a millisecond later.
Route change should fire all relevant navigation signals, but it shouldn't change the state until the old component has been unmounted, as otherwise it's creating side-effects
What does the proposed API look like?
the step 11 "dom updates triggered" here https://next.router.vuejs.org/guide/advanced/navigation-guards.html#the-full-navigation-resolution-flow should be split up into
unmount old component -> update route state -> mount new component
The text was updated successfully, but these errors were encountered: