sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.72k stars 4.13k forks source link

[AGAIN] Incorrect error message "... received an unexpected slot "default". #6325

Open YamiOdymel opened 3 years ago

YamiOdymel commented 3 years ago

Describe the bug

received an unexpected slot "XXXXXX" for all the slots which were used in the component.

Logs

index.mjs:1701 <ts-divider> received an unexpected slot "default".

To Reproduce

<div class="ts-divider">
    <!-- Text -->
    {#if $$slots.default}
    <div class="ts-divider__text">
        <div class="ts-divider__text__start">
            <div class="ts-divider__text__line"></div>
        </div>
        <div class="ts-divider__text__center">
            <slot></slot>
        </div>
        <div class="ts-divider__text__end">
            <div class="ts-divider__text__line"></div>
        </div>
    </div>
    {/if}
    <!-- / Text -->

    <!-- Line Only -->
    {#if !$$slots.default}
    <div class="ts-divider__line"></div>
    {/if}
    <!-- / Line Only -->
</div>

Expected behavior

No warning message should appeared.

Stacktraces If you have a stack trace to include, we recommend putting inside a <details> block for the sake of the thread's readability:

index.mjs:1701 <ts-divider> received an unexpected slot "default".
validate_slots @ index.mjs:1701
instance       @ Divider.svelte:132
init           @ index.mjs:1517
Divider        @ Divider.svelte:18
(anonymous)    @ Divider.svelte:18
(anonymous)    @ Divider.svelte:18

Information about your Svelte project:

Severity

It's not immediate just annoying warning messages.

Additional context

Re-open an new issue from Incorrect error message "... received an unexpected slot "default". #4546

tanhauhau commented 3 years ago

@YamiOdymel it would be great if you could provide a repl (https://svelte.dev/repl) / github repo that could replicate this issue?

YamiOdymel commented 3 years ago

@YamiOdymel it would be great if you could provide a repl (https://svelte.dev/repl) / github repo that could replicate this issue?

I think someone has replied with a command to reproduce the issue

@tanhauhau Sadly, the bug isn't fixed. I think this needs to be reopened.

Simple reproduction: npm init svelte@next slot-test && cd slot-test && npm i && npm run dev + open the browser dev-console. You don't need to write a single char of code to trigger it :)

frederikhors commented 3 years ago

@tanhauhau just a new svelte-kit project!

tanhauhau commented 3 years ago

@YamiOdymel @frederikhors yup.

@YamiOdymel just want to confirm, whether the one you are reporting is the same root cause of the issue from svelte kit

benmccann commented 3 years ago

@tanhauhau shared some notes with me. Putting them here for reference

for kit issue, it's because of code like this:

<script>
  let components = [Layout, Route];
</script>

<svelte:component this={components[0]} {...(props_0 || {})}>
  {#if components[1]}
    <svelte:component this={components[1]} {...(props_1 || {})}>
      {#if components[2]}
        <svelte:component this={components[2]} {...(props_2 || {})}/>
      {/if}
    </svelte:component>
  {/if}
</svelte:component>

the Route component receives a default slot of

{#if components[2]}
  <svelte:component this={components[2]} {...(props_2 || {})}/>
{/if}

even if components[2] is falsy. but Route isn't expecting any slot, therefore the warning.

because of how slot is implemented right now, we pass the whole "{#if}" block into the default <slot/>, doesn't care whether the if block condition is true / false. and the runtime warning checks if something is passed into the slot, even when the "something" renders nothing.

so, if we have a lot of __layout.svelte components, the generated code will be as many levels deep, thus when visiting a "shallow" route, you'll hit the "<Routes> received an unexpected slot "default"" warning

2 approaches:

ebeloded commented 3 years ago

Hey @benmccann! Thank you for the explanation.

Wouldn't the following resolve the issue in kit?

<svelte:component this={components[0]} {...(props_0 || {})}>
  {#if components[1]}
      {#if components[2]}
       <svelte:component this={components[1]} {...(props_1 || {})}>
          <svelte:component this={components[2]} {...(props_2 || {})}/>
       </svelte:component>
      {:else}
       <svelte:component this={components[1]} {...(props_1 || {})} />
      {/if}
  {/if}
</svelte:component>

If so, then https://github.com/sveltejs/kit/issues/981 can be resolved on its own.

bluwy commented 3 years ago

@ebeloded That's causes component[1] to unnecessarily remount if only component[2] changes, which is unexpected behaviour for end-users and could have side effects for transitions/animations.

techniq commented 3 years ago

@benmccann Approach #2 (passing #if into slot) might also resolve $$slots with slot forwarding

nilslindemann commented 2 years ago

For the records, This can also happen if one uses pug for writing the html, and accidentally calls the component like this: MyComponent (... my attribs ...), aka, have a whitespace between the component name and the brackets. Remove the whitespace and the message will disappear.

Borderliner commented 7 months ago

No fix yet? This is an extremely sad state of affairs.