Skip to content

[Bug]: Unexpected token 'default' - Storing sub-components as properties on Components #24665

Open

Description

Describe the bug

I'm building a component library using React / TypeScript / Vite. For a few components, I assign a sub-component as a property on another component, when their functionality is tied, e.g. in my case:

<Grid>
    <Grid.Cell>...</Grid.Cell>
    <Grid.Cell>...</Grid.Cell>
</Grid>

But furthermore, my export process looks something like:

export default function Grid() { ... }

export function Cell() { ... }

Grid.Cell = Cell;

Now, this pattern I've tested and confirmed that it works fine in a normal Vite project. But when running it specifically in the Storybook iframe, it fails with Unexpected token 'default'.

Because Grid is the default export, it appears the compiled code includes default in the exported code because it thinks that default.Cell is another component:

try {
    // @ts-ignore
    Grid.displayName = "Grid";
    // @ts-ignore
    Grid.__docgenInfo = { /* ... JSON details ... */ };
}
catch (__react_docgen_typescript_loader_error) { }
try {
    // @ts-ignore
    default.Cell.displayName = "default.Cell";
    // @ts-ignore
    default.Cell.__docgenInfo = { /* ... JSON details ... */ };
}
catch (__react_docgen_typescript_loader_error) { }
try {
    // @ts-ignore
    Cell.displayName = "Cell";
    // @ts-ignore
    Cell.__docgenInfo = { /* ... JSON details ... */ };
}
catch (__react_docgen_typescript_loader_error) { }

The default.Cell in the middle section is a syntax error, not even something try catch can handle. Thus the whole module throws the unhelpful error: Unexpected token 'default', even though VSCode, ESLint, etc. find no errors project-wide.

To Reproduce

It can be reproduced with the following component:

test.tsx

import React from "react"

export default function Test({children}:React.ComponentProps<"div">) {
	return (
		<div className="test">
			{children}
		</div>
	)
}

export function Sub({children}:React.ComponentProps<"div">) {
	return (
		<div className="sub">
			{children}
		</div>
	)
}

Test.Sub = Sub;

and the following story:

Test.stories.tsx

import React from "react";
import { Meta, StoryObj } from "@storybook/react";
import Test from "./test";

const meta = {
	title: "Test/Error Example",
	parameters: {
		layout: "centered",
	},
} satisfies Meta<typeof Test>

export default meta;

type Story = StoryObj<typeof meta>

export const Example:Story = {
	args: {},
	render: () => <>
		<Test>
			<Test.Sub>Hello World</Test.Sub>
		</Test>
	</>
}

But bear in mind, the storybook server must be started after the code is written.

That is,

  • Comment out the Test.Sub = Sub line of test.tsx
  • Save, then restart the server
  • Then uncomment it and save again

At this point, the storybook works fine. Restart the storybook server again, and it'll crash. I presume this means the code is only compiling during storybook startup time (or maybe I have a poor config?).

System

Output of npx storybook@latest info

Storybook Environment Info:

  System:
    OS: Windows 10 10.0.19045
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
  Binaries:
    Node: 18.18.0 - D:\Apps\nodejs\node.EXE
    npm: 9.8.1 - D:\Apps\nodejs\npm.CMD <----- active
    pnpm: 8.8.0 - D:\Apps\nodejs\pnpm.CMD
  Browsers:
    Edge: Spartan (44.19041.3570.0), Chromium (118.0.2088.76)
  npmPackages:
    @storybook/addon-essentials: ^7.5.2 => 7.5.2
    @storybook/addon-interactions: ^7.5.2 => 7.5.2
    @storybook/addon-links: ^7.5.2 => 7.5.2
    @storybook/addon-onboarding: ^1.0.8 => 1.0.8
    @storybook/blocks: ^7.5.2 => 7.5.2
    @storybook/react: ^7.5.2 => 7.5.2
    @storybook/react-vite: ^7.5.2 => 7.5.2
    @storybook/testing-library: ^0.2.2 => 0.2.2
    eslint-plugin-storybook: ^0.6.15 => 0.6.15
    storybook: ^7.5.2 => 7.5.2

Additional context

This seems like it may actually be a problem with @storybook/builder-vite or another package. As I couldn't really determine which, I figured I'd start by posting it here. But I will see if I can make any further discoveries on its source.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions