Reputation: 1474
I'm currently upgrading from Svelte 4 to Svelte 5 (using SvelteKit), and I'm encountering an issue when trying to replace the deprecated <slot />
with {@render}
in my components.
I'm looping through a series of components that make up a list with it's nested list elements. In Svelte 4, I used <slot />
to handle nested elements. Below is a simplified example of my setup:
<Component {node}>
{#if hasChildren(node)}
{#each node.children as child}
<svelte:self node={child} />
{/each}
{/if}
</Component>
<script lang="ts">
import type { List } from 'datocms-structured-text-utils';
let { node }: { node: List } = $props();
let { style } = $state(node);
</script>
{#if style === 'numbered'}
<ol><slot /></ol>
{:else}
<ul><slot /></ul>
{/if}
<script lang="ts">
import type { ListItem } from 'datocms-structured-text-utils';
let { node }: { node: ListItem } = $props();
</script>
<li><slot /></li>
In Svelte 5, <slot />
has been deprecated in favor of {@render}
. How can I adapt the logic I used with <slot />
to {@render}
in these components?
Specifically, I’m unsure about the correct argument to use inside {@render ...}
since render tags can only contain call expressions.
node
object{
"type": "list",
"style": "bulleted",
"children": [
{
"type": "listItem",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "span",
"value": "This is a list"
}
]
}
]
},
{
"type": "listItem",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "span",
"value": "More list items"
}
]
}
]
},
{
"type": "listItem",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "span",
"value": "Even more"
}
]
}
]
}
]
}
Any guidance on how to handle this would be appreciated!
Upvotes: 1
Views: 2298
Reputation: 1474
Thanks to user brunnerh I dug deeper into it and found the root cause: <svelte:self>
is also deprecated:
import Node from "./Node.svelte"
<Component {node}>
{#if hasChildren(node)}
{#each node.children as child}
/* This is deprecated: <svelte:self node={child} /> */
<Node node={child} />
{/each}
{/if}
</Component>
After updating <svelte:self />
by referencing the same component again, I have the correct export children()
i needed to use {@render children()}
:
<script lang="ts">
import type { ListItem } from 'datocms-structured-text-utils';
let { node, children }: { node: ListItem, children (): any; } = $props();
</script>
<li>{@render children()}</li>
Thanks mates.
Upvotes: 2
Reputation: 185280
<slot />
is migrated by adding a children
prop, which is implicitly created from the content passed to the component, and rendering that. E.g.
<script lang="ts">
import { type Snippet } from 'svelte';
let { children: Snippet } = $props();
</script>
{@render children()}
For how to migrate named slots, see this answer.
Upvotes: 3