svelte icon indicating copy to clipboard operation
svelte copied to clipboard

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

Open YamiOdymel opened this issue 4 years ago • 10 comments

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:

  • Your browser and the version: (e.x. Chrome 52.1, Firefox 48.0, IE 10): Chrome 90

  • Your operating system: (e.x. OS X 10, Ubuntu Linux 19.10, Windows XP, etc): Ubuntu 19.10

  • Svelte version (Please check you can reproduce the issue with the latest release!): ^3.38.1

  • Whether your project uses Webpack or Rollup: Rollup

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

YamiOdymel avatar May 14 '21 00:05 YamiOdymel

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

tanhauhau avatar Aug 05 '21 07:08 tanhauhau

@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 :)

YamiOdymel avatar Aug 05 '21 07:08 YamiOdymel

@tanhauhau just a new svelte-kit project!

frederikhors avatar Aug 05 '21 08:08 frederikhors

@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

tanhauhau avatar Aug 05 '21 08:08 tanhauhau

@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:

  • suppress the warning (there's no such option in svelte yet)
  • support passing {#if} into slot, as in able to know that there'll be no content, if the condition is false, therefore do not warn + render slot fallback (https://github.com/sveltejs/svelte/issues/6218)

benmccann avatar Aug 13 '21 04:08 benmccann

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.

ebeloded avatar Aug 13 '21 05:08 ebeloded

@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.

bluwy avatar Aug 13 '21 07:08 bluwy

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

techniq avatar Aug 13 '21 11:08 techniq

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.

nilslindemann avatar Jan 13 '22 11:01 nilslindemann

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

Borderliner avatar Feb 16 '24 01:02 Borderliner