This question is in reference to
Pass in a slot to a recursive component
App.svelte
<script>
import Tree from './Tree.svelte';
const items = [
{
type: 'person', first: 'Maru', last: 'Doe',
children: [
{ type: 'person', first: 'Pochi', last: 'Doe' },
{ type: 'person', first: 'Tama', last: 'Doe' },
{ type: 'thing', manufacturer: 'ACME', product: 'missiles' },
]
}
]
</script>
<Tree {items} let:item>
{#if item.type == 'person'}
{item.last}, {item.first}
{:else if item.type == 'thing'}
{item.product} ({item.manufacturer})
{/if}
</Tree>
Tree.svelte
<script>
export let items;
export let level = 0;
</script>
<div style:margin-left="{level * 20}px">
{#each items as item}
{(console.log({item}),'')} ---> all items are shown here
<slot item={item} />
<svelte:self items={item.children ?? []} level={level + 1}
let:item={child}>
<slot item={child} />
</svelte:self>
{/each}
</div>
In Tree.svelte, if we remove <slot item={child} />
only the parent item is shown i.e. Maru Doe.
But we have the following line(in Tree.svelte) <slot item={item} />
and if we console print item
we get all the items i.e. Pochi, Tama, ACME. Should <slot item={item} />
not pass item
to the parent (App.svelte) for the items to be printed in each recursion?
So, why are these not displayed when removing <slot item={child} />?
When is <slot item={child} />
called? Is it like this, svelte:self calls itself recursively and when the last child object is reached, <slot item={child} />
is called?
It is necessary for recursion.
If the <svelte:self>
does not have any content (regardless of whether that is a <slot>
or something else), it will not know how to display the items as that is passed onto <slot>
within the component.
So if that is not set, the upper <slot>
definition is used to render the items at the current level, but for any children of these items, nothing will be specified.
<slot item={child} />
is not just used for some specific item, it is used for all items that are passed in via <svelte:self items={item.children ?? []} ...
.
In the template that is this:
{#each items as item}
<slot item={item} />
You could think of it as a function like this, maybe that helps:
function tree(items, render) {
for (const item of items) {
render(item);
// `render` needs to be passed again
tree(item.children ?? [], render);
}
}