-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the bug
We're trying to upgrade to Svelte 5 at my company, but we ran into this bug when trying to migrate our portals implementation.
In short, the goal with portals is to allow a child component to insert one of its elements into an element of another component via an imported reference, instead of prop drilling. I'll spare you the other details and get right into the issue.
This is the bug:
First we have a file with an exported object containing a snippet:
// portals.svelte.js
export let headerPortal = $state({ snippet: null });And our App.svelte renders this snippet, as well as containing a dynamic component:
<script>
import { headerPortal } from './portals.svelte'
let route = { component: ..., props: ... }
</script>
{#if headerPortal.snippet !== null}
<header>
{@render headerPortal.snippet()}
</header>
{/if}
<route.component {...route.props} />Then we have a component that sets headerPortal.snippet. The snippet has to contain a reference to a prop (2-levels deep):
<script>
import { headerPortal } from "./portals.svelte";
let { data } = $props();
$effect.pre(() => {
headerPortal.snippet = mySnippet;
return () => {
headerPortal.snippet = null;
};
});
</script>
{#snippet mySnippet()}
<h1>{data.text}</h1>
{/snippet}If we use our dynamic component in App.svelte to mount this one, and then unmount it, then we will get an error:
Uncaught TypeError: Cannot read properties of undefined (reading 'text')
Reproduction
Bug REPL
Open the console and click "Show page 2" and then "Show page 1". You should see an error, similar to the one above.
https://svelte.dev/playground/1175b32356ca41d4953c2896f71871ac?version=5.16.0
I haven't been able to reduce it any further.
Workaround REPL
https://svelte.dev/playground/c214d0b1cb5c4e6cba00c85a3704391f?version=5.16.0
It makes a change to the router:
<script>
let route = ...
let someKey = $state(0) // increment whenever route changes
</script>
{#if route !== null}
{#each [route] as route (someKey)}
<route.component {...route.props} />
{/each}
{/if}It's a complete hack. I expected {#key someKey } to work the same way, but it doesn't. It has to be a keyed each block
Logs
No response
System Info
System:
OS: Windows 11 10.0.26100
CPU: (16) x64 AMD Ryzen 9 6900HS with Radeon Graphics
Memory: 16.66 GB / 31.25 GB
Binaries:
Node: 20.12.2 - C:\Program Files\nodejs\node.EXE
npm: 10.5.2 - C:\Program Files\nodejs\npm.CMD
pnpm: 9.12.3 - C:\Program Files\nodejs\pnpm.CMD
Browsers:
Edge: Chromium (131.0.2903.112)
Internet Explorer: 11.0.26100.1882Severity
annoyance