storybook icon indicating copy to clipboard operation
storybook copied to clipboard

Addon-docs: Error: Evaluation failed: TypeError: Cannot convert a Symbol value to a string

Open FabianSellmann opened this issue 3 years ago • 28 comments

Describe the bug The error Error: Evaluation failed: TypeError: Cannot convert a Symbol value to a string is thrown at runtime for a story under the cirucmenstance described below. To Reproduce Steps to reproduce the behavior:

  1. Have story wrapped in a React.Profiler
  2. Have docs addon enabled
  3. Open story in story book Expected behavior It should not throw this error

Using storybook v6.0-rc3

Traced it down that the error originates here: https://github.com/algolia/react-element-to-jsx-string/blob/c4908bbb52e58e104c9d42d1ceaff80d53fd4bdf/src/formatter/formatReactElementNode.js#L122

The react-element-to-jsx-string package is a dependency is a dependency of the docs addon.

While I dont have the time to build a repro case right now, I think it should be fairly easy to do with the information provided. Hope this helps. Best regards.

FabianSellmann avatar Jul 15 '20 06:07 FabianSellmann

As a workaround you can set the docs.source.type story parameter to "code".

shilman avatar Sep 01 '20 00:09 shilman

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

stale[bot] avatar Dec 25 '20 16:12 stale[bot]

NOTE: this is needed to put a <React.Suspense> wrapper for performance optimizations (h/t @sokra) -- will see if i can expedite a fix.

shilman avatar Feb 20 '21 15:02 shilman

I am having the same problem as listed in #14020

Here's my workaround so the 'view code' sample looks right:

import React, { Suspense } from 'react';
import { Story, Meta } from '@storybook/react';

import AppLazyLoadedTemp from './AppLazyLoaded';

const AppLazyLoaded = (props: any) => {
  return <Suspense fallback={<p>Please wait...</p>}><AppLazyLoadedTemp {...props} /></Suspense>;
}

export default {
  title: 'AppLazyLoaded',
  component: AppLazyLoaded,
  argTypes: {
  },
} as Meta;

const Template: Story<{}> = (args) => <AppLazyLoaded {...args} />;

export const Demo = Template.bind({});
Demo.args = {};

Shane32 avatar Apr 06 '21 22:04 Shane32

As a workaround you can set the docs.source.type story parameter to "code".

It is not friendly for using template mode. The code will be displayed as

(args) => <Component {...args} />;

How to write stories if set type to code???

xyy94813 avatar May 13 '21 14:05 xyy94813

@xyy94813 that's why it's a workaround an not a solution. But you can set the code to whatever string you want.

shilman avatar May 14 '21 01:05 shilman

Someone is trying to fix it... https://github.com/algolia/react-element-to-jsx-string/pull/515

xyy94813 avatar May 14 '21 02:05 xyy94813

As a workaround you can set the docs.source.type story parameter to "code".

It is not friendly for using template mode. The code will be displayed as

(args) => <Component {...args} />;

How to write stories if set type to code???

Here's how, it doesn't affect the story, only the "Docs" page/addon.

export const MyStory = Template.bind({});
MyStory.args = {
    key: "Property",
}
/* 👇🏻 here is the workaround */
  MyStory.parameters = {
    docs: {
      source: {
        code: "Disabled for this story, see https://github.com/storybookjs/storybook/issues/11554"
      }
    }
  }

danielthedifficult avatar Aug 05 '21 12:08 danielthedifficult

it will resolve by https://github.com/algolia/react-element-to-jsx-string/pull/617.

xyy94813 avatar Sep 29 '21 03:09 xyy94813

For @storybook/addon-docs, i think react-element to source code is not correct way. It will make more complex when use Lazy component.

xyy94813 avatar Sep 29 '21 03:09 xyy94813

@xyy94813 I cloned react-element-to-jsx-string repo and npm linked it to my project and it does not resolve the issue. Also they haven't released in over a year. And I agree that the above workaround is not ideal. @shilman any glimmer of hope on this?

protoEvangelion avatar Oct 18 '21 23:10 protoEvangelion

Has there been any progress with this? I'm still currently experiencing this problem with 6.3.12

davidmenendez avatar Nov 16 '21 20:11 davidmenendez

@davidmenendez yes here is a babel plugin I added which works. You might have to adjust the replace functions with something that works better for your code:

const template = require('@babel/template')

/**
 * Adding this babel transformer supports the src code view with Suspense
 * Until this issue is resolved, we have to add the src code docs ourselves:
 * https://github.com/storybookjs/storybook/issues/11554
 * The approach is to grab the src code for the entire file, and then strip out unecessary things
 * like large file header helpers that storybook injects so we only show the essentials.
 */
module.exports = () => {
  return {
    visitor: {
      Program(path, state) {
        if (state.file.opts.filename.endsWith('.stories.tsx')) {
          const srcCode = path.hub.file.code
            .trim()
            .replace(
              /(.*((__(STORY|LOCATIONS_MAP)__)|(\/\/)|(\/\*)|(@storybook\/react)|(Template\.parameters =))|(Template\.storyName)).*/g,
              ''
            )
            .replace(/.*React\.Suspense.*\n/gm, '')
            .replace(/export default.*Meta/s, '')
            .replace(/\n\s*\n/g, '\n\n')

          path.node.body.push(
            template.default.ast(`
Template.parameters = {
    ...Template.parameters,
    docs: {
        source: {
            code: \`${srcCode}\`
        }
    }
};`)
          )
        }
      }
    }
  }
}

In your main.js file:

module.exports = {
  stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: ['@storybook/addon-essentials'],
  babel: async config => {
    return {
      ...config,
      plugins: [
        ...config.plugins,
        path.resolve(__dirname, './babel-docs-plugin.js')
      ]
    }
  },

Here is a working lazy loaded component:

image

protoEvangelion avatar Nov 17 '21 00:11 protoEvangelion

I saw this error after upgrading to 6.4. It worked fine previously. I created an example repository for this. Is this actually Storybook problem or react-element-to-jsx-string or something completely else? Are we doing something wrong?

(Note: This workaround helps.)

donaldpipowitch avatar Jan 07 '22 12:01 donaldpipowitch

I'm still running into this issue over 2 years later 😞

I wanted to add a withSuspense decorator so any storybook components I have that relies on Suspense would be able to render.

But getting the same error:

Cannot convert a Symbol value to a string

The workaround works for individual components. However it would be better if there was a "global" solution.

I'm now having to go through all of our stories to:

  • import { Suspense } from 'react'
  • wrap the component in the story with `<Suspense>...</Suspense>
  • Define and override parameters for that story:
story.parameters = {
  docs: {
    source: {
      code: 'Disabled for this story, see https://github.com/storybookjs/storybook/issues/11554',
    },
  },
}

x100 for all our of storybook components that rely on Suspense after upgrading.

Does anyone know of a way to solve this problem at the storybook level instead of individual stories? in preview or main files?

MarkLyck avatar Aug 23 '22 16:08 MarkLyck

Submitted a PR here: https://github.com/storybookjs/storybook/pull/19004

zhyd1997 avatar Aug 25 '22 02:08 zhyd1997

Yo-ho-ho!! I just released https://github.com/storybookjs/storybook/releases/tag/v7.0.0-alpha.46 containing PR #19004 that references this issue. Upgrade today to the @next NPM tag to try it out!

npx sb upgrade --prerelease

Closing this issue. Please re-open if you think there's still more to do.

shilman avatar Oct 28 '22 14:10 shilman

This issue still exists using 7.0.0-alpha.48

decorators: [(Story) => <Suspense>{Story()}</Suspense>]

gives the error

Cannot convert a Symbol value to a string

sirganya avatar Nov 08 '22 12:11 sirganya

Maybe we need to find a way let https://github.com/storybookjs/storybook/blob/9a07fcba8a581558d0fa8262989ef83b70a507a0/code/renderers/react/src/docs/jsxDecorator.tsx#L77 inherit this: https://github.com/algolia/react-element-to-jsx-string/blob/984f26908c17cea134fa53d17ac51f179e5195b2/src/parser/parseReactElement.js#L74

zhyd1997 avatar Nov 08 '22 13:11 zhyd1997

Handled by PR #19785

zhyd1997 avatar Nov 09 '22 02:11 zhyd1997

Hello, the PR #19785 has not been merged and this is still an issue. Using i18next in a global decorator is a common use case where the current issue occurs. Any plans to fix this?

triglian avatar Mar 09 '23 12:03 triglian

Issue persists in 7.0.0-beta.64

shulcsm avatar Mar 09 '23 13:03 shulcsm

#19785

@zhyd1997 and @shilman , any update on this PR as the issue is still remaining as mentioned above.

fizz3r avatar Apr 05 '23 07:04 fizz3r

I am seeing this error using Storybook ~7.0.18~ 7.0.20 with Vite and React. Haven't been able to pin down what exactly what is causing the problem. Using the docs workaround until this gets fixed.

@shilman Can we re-open this issue? I see the PR mentioned above is still open.

KorySchneider avatar Jun 07 '23 11:06 KorySchneider

I am also seeing this issue in SB7 + React.

jclarkcisco avatar Jul 26 '23 20:07 jclarkcisco

Here's another workaround

const ReactSuspense = ({ children }: { children: React.ReactNode }) => <React.Suspense>{children}</React.Suspense>;

export function withSuspense<TFramework extends AnyFramework = AnyFramework, TArgs = Args>(
  story: PartialStoryFn<TFramework, TArgs>,
  ctx: StoryContext<TFramework, TArgs>,
) {
  return (
    <ReactSuspense>
      <>{story(ctx)}</>
    </ReactSuspense>
  );
}

alexgorbatchev avatar Nov 22 '23 01:11 alexgorbatchev

I noticed this issue is happening only when there are arguments in a story. For example, this will throw the error Cannot convert a Symbol value to a string:

    render: (args) => {
        const iconName =  args.icon;
        const Icon = useMemo(() => lazy(() => import(`../../../foundation/Icons/tsx/${iconName}`).then((module) => ({ default: module[iconName] }))), [iconName]);

But without "args", it work flawlessly:

    render: () => {
        const iconName =  "Homeline";
        const Icon = useMemo(() => lazy(() => import(`../../../foundation/Icons/tsx/${iconName}`).then((module) => ({ default: module[iconName] }))), [iconName]);

RowinVanAmsterdam avatar Dec 05 '23 21:12 RowinVanAmsterdam

This is still an issue in 7.6.16.

Using a <Suspense> or anything related inside a render functions seems to trigger it, which is pretty bad, considering this is fairly common.

jaens avatar Feb 16 '24 14:02 jaens