Before and after hooks for routing
See original GitHub issueDescribe the bug
onMount
is not fired on page change, if the actual page component doesn’t change. This is all routes which contain [dynamic] parameters, since the underlying components are the same.
To Reproduce Reproduction here:
https://github.com/beyonk-adventures/sapper-onmount-issue
The colour pages set the value from the path parameters on load, and onMount sets the value in the page. Because onMount isn’t refired, the colour never changes when clicking between pages, only on hard refresh, or when visiting the home page and then clicking a new colour.
Essentially it means you can’t change the content of the page unless you visit an url which results in a completely different page component being loaded.
Expected behavior
Though using the same physical page component, /different/routes
and /different/paths
which map to /different/[parameter].svelte
should fire onMount, since the route is changing.
Information about your Sapper Installation:
- Sapper └── sapper@0.27.16
Severity Extremely High. I don’t actually know how to work around this.
Additional context Fixing this would be a breaking change, but I think it’s far more logical an approach than the current behaviour.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:39
- Comments:71 (45 by maintainers)
Top GitHub Comments
After trying to find a reasonable way around this now, I’m 99% erring on this behaviour being a bug / broken feature.
Not having the ability to use
onMount
andonDestroy
means you have to write your own change logic for every component and sub-component which sits underneath your top-level component.Listening for the
$page
store to change is fine if you’re only one component deep, but the amount of subscribing/reactive declarations you need to get everything in the hierarchy to update just becomes unmaintainable very quickly.Being able to rely on components mounting and un-mounting is the only sensible way I can think here of restoring state, since if you think about it, a route change is akin to “tearing down” the page component and “mounting” a new page component.
IMO this is 100% a bug and the fact that it accidentally has some benefits is irrelevant. Let me try to convince you all:
The problem is that the developer now has to consider not just where a user is but how she got there (or where she is coming from) to reason about their app. Consider @antony’s example where there are 3 views:
And the dynamic params at the top level:
This example is very plausible if it is e.g.
team
anduser
instead offish
andhorse
. If the user navigates from horse 1 to fish 1, she will be in one state (new content loaded). If a user navigates from fish 1 to fish 2 directly, she will be in a different/inconsistent state (no new content loaded). But if the user who got to fish 2 via fish 1 refreshes her browser, she’ll see different content.Consider these two functions:
I’d argue that they should behave exactly the same way. The user is navigating to the same view; the developer took the recommendation to use Sapper’s
goto
when handling navigation. But if the developer uses the first function on anyfish
pages, the two functions will not behave the same way.IMO the URL represents where the user is regardless of how they got there, and Sapper should default to idempotence: a request produces the same result every time.
To address the examples of a photo album or ecommerce site, I see those as performance optimizations. You presumably know where the user is coming from (another photo or another item of a certain type) and going to, so you want to optimize the transition and possibly add an animation. Sure! Why not just make
{remount: true}
the default and if you happen to know you’re going from one photo to another, you can optimize by passing{remount: false}
?