[Bug]: Unexpected token 'default' - Storing sub-components as properties on Components
#24665 opened on Nov 2, 2023
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 = Subline oftest.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.