Open ufoscout opened 2 years ago
Only after reading #4895 I found that we have the same issue in production. An option to change the behaviour would be great.
Opened a discussion about this here: https://github.com/sveltejs/kit/discussions/5007
Moved this to the post-1.0 milestone, since after discussing people's use cases in #5007 it's clear than a boolean preserve
option wouldn't suffice (and we don't have a place to return it from load
post-#5748 anyway), and we'd be able to add a solution to this post-1.0 in a non-breaking way if we decided to.
In my head, something like this in +page.js
(or +page.server.js
) could work:
export function key({ url }) {
return url.pathname; // component always remounts if pathname changes, but not if query string does
}
In the meantime, it's easy to do in userland...
{#key $page.url.pathname}
<!-- the component contents -->
{/key}
...the only drawback being that it won't re-run code inside your <script>
. (This is easy to fix just by moving everything into a sibling component that +page.svelte
imports.)
Here's an quick way to implement the workaround:
1) Rename +page.svelte
to page.svelte
.
2) Paste this into a new +page.svelte
.
<script lang="ts">
import { page } from '$app/stores';
import Page from './page.svelte';
export let data;
</script>
<!-- This is an workaround for: https://github.com/sveltejs/kit/issues/4941 -->
{#key $page.url.pathname}
<Page {data} />
{/key}
Edit: Pass through data
from +layout.ts
.
@Rich-Harris Is there any update to this? I understand the logic behind this as a feature, but feels like a giant point of friction for what should be a number of common use cases (navigating between blog entries)
i also hit this - i rely on the load function to fetch data from the api based on query params
I hate to be one those "+1" people, but yeah this is such an unexpected area of SvelteKit that should really be made consistent. Everything works fine without reactive assignments, until I also added links to articles within my articles, and I would not see the new article even though the load function was called, the GET request to fetch the new article was made.
Is it really that bad to run the script tag again? You do it when I navigate from /articles/one to /articles and then to /articles/two, why not do it when I go from /articles/one to /articles/two?
I've ran into this issue, as well, and it's also a wanted update on my end. Instead of the more intricate workaround provided earlier in this thread, my team is going with adding the data-sveltekit-reload attribute to all of our anchor tags which would result in same page navigation. I realize this workaround might not be suitable for everyone, but if you're in a situation like our team, then the data-sveltekit-reload workaround is much easier to clean up after this issue is resolved.
<!-- data-sveltekit-reload forces svelte to reload the page as if you're navigating to it for the first time -->
<a data-sveltekit-reload href="...">link here</a>
To add onto this, it also seems like this issue has a similar effect with
This is still a major issue. Maybe I'm missing something in the docs?
I have an e-commerce site and many products share catch-all routes. When a user navigates to another product on the same route many of the components are preserved. What's more frustrating is that the behavior seems inconsistent, some sub-components update while others do not.
I have a live example on our staging server here: https://sourceone.parts/brands/cummins/assembly/2864025.
If you click on a breadcrumb and choose another product, it works fine. However, we have recommended products at the bottom of the page. Clicking on those links updates the majority of the product page components, but the image gallery doesn't update the images even though the entire product data model has changed.
Right now, +page.server.js fetches the new product from the backend and loads a new product in the pages data.
I've been using Sapper for years and we just migrated to Kit. Issues like this are holding us back from releasing our new version. I've been banging my head against this for a few weeks now trying to find a solution. Again, I apologize if this has been answered somewhere but I'm not finding it.
Edit: Just found out about the #key directive and that seems to do the job.
What's wrong with the {#key ...}
approach? It's what it's designed for.
It gives you the exact granularity you need — you can wrap the <slot></slot>
or {@render children()}
in your +layout.svelte
to re-render child layouts or the +page.svelte
, or you can re-render individual components, based on whichever change is relevant. This is much better than less-flexible page config, or the nuclear option of reloading the entire page.
It sounds like we just need to add something to the docs that makes this clearer?
Why won't this behavior be made consistent by default, without relying on that {#key ...}
workaround?
Like I said in a previous comment: Is it really that bad to run the script tag again? You do it when I navigate from /articles/one to /articles and then to /articles/two, why not do it when I go from /articles/one to /articles/two?
It really is a major point of confusion.
When you write a component, your job is to make sure that it stays consistent with its props. You wouldn't blame the framework if <Hello {name} />
didn't update to reflect a new name
, and you certainly wouldn't expect the framework to remove the component entirely and reinsert it when name
changed.
Pages are just components. What you're asking for is for them to be made inconsistent by default. Why stop at pages? What rationale, other than a gut feeling, justifies replacing one but not the other?
There are many situations where it's essential to keep the component on the page. Consider something like svelte.dev/tutorial/kit — if we did what you suggest, you would see 'booting webcontainer' on every navigation. There are lots of cases where you need to keep the page component alive, not just because it would be absurdly wasteful to default to removing and recreating it, but because the app would be broken otherwise.
So you'd need some new API for counteracting the wasteful inconsistency you've just introduced, even though we already have a perfectly good API — {#key ...}
— for achieving the outcome you want.
If this is really a major point of confusion (it isn't, this topic has come up very infrequently and hasn't been widely upvoted!) then the solution is to improve the documentation, not degrade the framework.
Describe the problem
This is a follow up from #4895
When navigating to a new link, Sveltekit behaves differently if the link is handled by the same route or a different one; this can happen every time a route contains a slug. For example:
Preconditions:
Case 1:
/two
to/one/something
, theone/[slug].svelte
component is instanciated and it's<script>
section is executed as expected/one/something
to/two
, theone/[slug].svelte
is deinstanciatedCase 2:
/one/other
to/one/something
, theone/[slug].svelte
component is not re-instanciated and the it's<script>
section is not executedthis leads to a page that behaves differently based on where the user was before navigating to it. A consequence of the fact that the
<script>
is not executed, is that all variables defined in it are not updated as expected.Describe the proposed solution
I would definitely prefer that by default Sveltekit behaves consistently on every route change no matter the previous route. Anyway, having a global option in
svelte.config.js
to enable this behaviour would solve the issue.Alternatives considered
No response
Importance
would make my life easier
Additional Information
No response