-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Description
Astro Info
Astro v4.15.4
Node v20.17.0
System Linux (x64)
Package Manager unknown
Output static
Adapter none
Integrations @astrojs/tailwind
@astrojs/svelte
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
When using thetransition:persist directive on svelte-components two errors occur:
- The state is not persisting (which is ok since you can opt out with transition:persist-props)
- The eventlisteners are not removed (e.g. on:click)
The second issue is extremly problematic, since it will stack all eventlisteners on rerouting:
In the example provided is a simple counter component made with svelte, with the viewtransition persist directive.
<header style="padding:3rem ">
<a style="color:white" href="/hello">hello</a>
<a style="color:white" href="/">home</a>
<Counter client:load transition:persist></Counter>
</header>Counter.svelte:
<script lang="ts">
import {sampleState} from "../state/sampleState.ts";
import {onMount} from "svelte";
function update(){
sampleState.update(e => e+1)
console.log("update")
}
onMount(() => {
console.log("mounted")
})
</script>
<button style="padding: 1rem;" on:click={update}>{$sampleState}</button>The update function will be called with each click, multiplied with amount of navigations when the user uses a link to navigate.
The example has two links and pages: "home", "hello".
As soon as you navigate by link, the component gets rerendered and the eventlisteners of on:click will not get destroyed.
The component will be mounted multiple times (per navigation) but the eventlistener will not get destroyed, leading to the "update" function getting called multiple times per click.
Hence it will not count by +1, but count by 1 + navigations.
On destroy and On Mount will be called, per navigation.
This bug is appearing from version 4.5.0 Onward.
I discovered it when upgrading from 4.3.7.
The latest version in which transition:persist works correctly is: 4.4.15 .
I hope this may help you
Current solution is: You have to opt out of the rerender with "transition:persist-props"
What's the expected result?
Events are only emitted once.
State is persisted.
And if component gets destroyed and rerendered, all framwork defined eventlisteners get removed.
With Astro Version 4.4.15 this problem did not occur.
Here is the example with that version: https://stackblitz.com/edit/github-xyb8rc-rruld2
Counter counts. Component trigger only one callback per click. State is persisted
Link to Minimal Reproducible Example
https://stackblitz.com/edit/github-xyb8rc
Participation
- I am willing to submit a pull request for this issue.