Storybook: Svelte: previousComponent.$destroy() error

Created on 24 Feb 2020  路  3Comments  路  Source: storybookjs/storybook

Bug:

Each time I navigate to another component, this happens:

previousComponent.$destroy is not a function

TypeError: previousComponent.$destroy is not a function
    at cleanUpPreviousStory (http://localhost:57830/vendors~main.8c2c12a870a4616bbce4.bundle.js:6291:21)
    at render (http://localhost:57830/vendors~main.8c2c12a870a4616bbce4.bundle.js:6382:3)
    at _callee$ (http://localhost:57830/vendors~main.8c2c12a870a4616bbce4.bundle.js:4592:30)
    at tryCatch (http://localhost:57830/vendors~main.8c2c12a870a4616bbce4.bundle.js:78460:40)

Which i noticed is here:

storybook/app/svelte/src/client/preview/render.ts
function cleanUpPreviousStory() {
  if (!previousComponent) {
    return;
  }
  previousComponent.$destroy();
  previousComponent = null;
}

From the looks of it, it seems like it doesnt have the $destroy function on there:

Screen Shot 2020-02-24 at 9 04 06 AM

Sample Story I used in svelte

import Badge from '../Badge.svelte';

export default { title: 'Badge Component' };

export const withGray = () => ({
  Component: Badge,
  props: {
    variation: 'grey',
    text: 'Grey Badge',
  },
});

export const withGreen = () => ({
  Component: Badge,
  props: {
    variation: 'green',
    text: 'Green Badge',
  },
});

export const withGreenAndANumber = () => ({
  Component: Badge,
  props: {
    variation: 'green',
    text: 'Green Badge',
    number: '3',
  },
});

Svelte Component

<script>
  // Props
  export let variation;
  export let text;
  export let number;
</script>

<span class="badge {variation}">
  {#if number} {number} {/if} {text} 
</span>

Versions:

  • "svelte": "^3.17.3"
  • "@storybook/svelte": "^5.3.13"

Thanks in advance for help!

svelte bug has workaround help wanted

Most helpful comment

Found out the issue:

I had imported my existing webpack and that was causing issues, specifically with the svelte-loader options.

Might be a good idea to include in the documentation to not use these options :

options: {
            dev: true,
            emitCss: true,
            hotReload: true,
          },

That was causing the majority of my problems and it was directly related to the error shown.
@cam-stitt @plumpNation @rixo

Once i did this:

module.exports = {
  stories: ['../src/**/*.stories.*'],
  webpackFinal: async (config) => {
    config.resolve.alias.svelte = path.resolve('node_modules', 'svelte');

    config.module.rules.push({
      test: /\.svelte$/,
      use: {
        loader: 'svelte-loader',
        options: {
          preprocess: autoPreprocess,
        },
      }
    })
    return config;
  },
};

Then i was fine, and did not include my custom webpack config.

All 3 comments

Just as a heads up, all i did as a quick fix/patch was a check on it:
previousComponent.$destroy && previousComponent.$destroy();

But obviously, that is not a real solution. I did this, just to get work done for now.

Found out the issue:

I had imported my existing webpack and that was causing issues, specifically with the svelte-loader options.

Might be a good idea to include in the documentation to not use these options :

options: {
            dev: true,
            emitCss: true,
            hotReload: true,
          },

That was causing the majority of my problems and it was directly related to the error shown.
@cam-stitt @plumpNation @rixo

Once i did this:

module.exports = {
  stories: ['../src/**/*.stories.*'],
  webpackFinal: async (config) => {
    config.resolve.alias.svelte = path.resolve('node_modules', 'svelte');

    config.module.rules.push({
      test: /\.svelte$/,
      use: {
        loader: 'svelte-loader',
        options: {
          preprocess: autoPreprocess,
        },
      }
    })
    return config;
  },
};

Then i was fine, and did not include my custom webpack config.

Just to add to the great answer by @badman-rodriguez, the emitCss option is actually needed if, for instance, you want that CSS processed by some other loader in your webpack config (e.g. processing background images via file-loader).

My resolve was to unset svelte-loaders hot-reloading options:

for (const rule of storybookConfig.module.rules) {
  for (const use of (Array.isArray(rule.use) ? rule.use : [rule.use])) {
    if (use.loader === 'svelte-loader') {
      use.options = {
        ...use.options,
        dev: undefined,
        hotReload: undefined,
      }
    }
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

bpeab picture bpeab  路  70Comments

joeruello picture joeruello  路  79Comments

firaskrichi picture firaskrichi  路  61Comments

ilias-t picture ilias-t  路  73Comments

p3k picture p3k  路  61Comments