storybook: Import order wrongly causing "Element type is invalid" errors in stories
Description
When using a component import/export entry-point for terse imports throughout the application the order of imports can cause unexpected errors in Storybook only; not in the yarn start environment or compiled application. The error is:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Imagine we have a components/ directory, in which we have an import/export entry-point index.js and each component has its own directory A/ and B/.
src/components/index.js:
// This order causes no errors in `yarn start` but causes an error in the story for component A
import { A } from "./A";
import { B } from "./B";
// This order causes no errors anywhere
// import { B } from "./B";
// import { A } from "./A";
// It doesn't matter in which order we export (A,B or B,A), only the order of the import causes the error
export { A, B };
This behaviour only appears to affect a component if it itself imports another component which appears below itself in the import/export entry-point.
For example in the above example component A itself imports component B to use within its render, and the only way to avoid the error in the story for component A is to remove component B from it or to swap the order of the imports in src/components/index.js.
Reproduction repo below for simpler demonstration.
To Reproduce
I understand that the description may be a little confusing to follow so I have created a barebones CRA + Storybook + 2 components reproduction repository which also causes the error.
Reproduction: https://github.com/chrisdunnbirch/storybook-import-bug
- Clone
git@github.com:chrisdunnbirch/storybook-import-bug.git - Run
yarn install - Run
yarn storybook - Check
A > Storyin Storybook (should render with above error) a. Runyarn start(should render as expected: “AB”) - Comment lines 4-5 and uncomment lines 8-9 in
src/components/index.js - Check
A > Storyin Storybook (should render as expected: “AB”)
Expected behavior
The story renders without error, as expected based on the behaviour of the yarn start environment and compiled application.
System
I first noticed this in a large TypeScript project which at the time had 5.3.0-rc.10 installed and the issue is still present in 5.3.6. The example reproduction repo above is the absolute barebones CRA + Storybook + 2 components with no TypeScript.
Additional context
It is worth noting that I have added a .env with NODE_PATH=src to recreate the behaviour of absolute imports that the CRA TypeScript preset allows by default.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 5
- Comments: 35 (11 by maintainers)
Commits related to this issue
- Bump version of PrismJS to fix import issue in Storybook https://github.com/storybookjs/storybook/issues/9516 — committed to guardian/dotcom-rendering by oliverlloyd 3 years ago
Also having this problem on Storybook 6
storybook version 6.2.1 resolves this issue for me
I have version 6.2.2 and still gets this issue.
Edit: It only happens in the Docs tab.
@cosmy81 Any chance you might have gotten this resolved or found a workaround aside from
import Title from "components/Title";?I am having a similar issue after copying over my components into a new project and installing a fresh StoryBook. The SB version in both projects is 5.3.19. One works perfectly with the same components and structure, and the other is failing with
Element type is invaliderror, only in StoryBook (the app is fine).The way I import the modules is very similar to what @chrisdunnbirch described. The issue is only with a
Buttoncomponent that imports aProgresscomponent. All other modules work fine, even those that import other components. The syntax is the same in every module.Directory structure
Button module
Progress module
Top level index
The story
The failing story file looks like this:
Workaround 1A
If I import the
Buttonto the story more directly, it works……but only if I also remove the export from the top-level index file:
Workaround 1B
It also works if no modules are imported from the index file:
Workaround 2
Another way is to change how the
Buttonmodule importsProgress:Workaround 3
It also works if the story doesn’t activate the the
Progressmodule (so it doesn’t get rendered):Replicating the button
I wanted to see what happens if I create a new
Buttonmodule with the same code but different name (Butt). The stories failed for both (they both existed in the project at the same time, so that I saw two errored stories while the rest were all good).I also renamed
ButttoLabel, but the error stayed.Changing Progress to another component
It seems it doesn’t matter if
ButtonimportsProgressor another component. The error happened with other components too. For example:@mrmckeb i think we can detect & warn?
Hi @nocarroll, I can definitely see presets/plugins that would be duplicates in this setup. Is this a project Babel config or for Storybook?
@shilman We’ll probably need to add some automatic filtering of duplicate plugins/presets in future… I’m not sure of the best way to do that now though.
Hi @mrmckeb here are the babel and storybook related packages in my
package.jsonand this is my
.babelrcThe
.babelrcis unchanged from when I was running Storybook 3.4.11 except for swapping"transform-class-properties"for"@babel/plugin-proposal-class-properties"I think the spec option is not actually read by the plugin but I included it since it’s still in my WIP branch for upgrading to Storybook 5.
Webpack should figure everything out for you but yeah that seems like a sensible approach in general.
It is worth noting again, for anyone reading now, that the error doesn’t appear in either the development or production application. It only appears in Storybook (wrongly I believe).
Maybe it is, I don’t really know. It seems to make sense that that is a good idea.
There are often cases where I need to import multiple components for use in a story and whereever possible I prefer to keep my code clean. For example
import { A, D, M, N } from "components";is much cleaner than:Regardless of what is best practice, I’ve been using Storybook for around a year and this error has only just begun wrongly appearing so should probably be fixed in case others may encounter it.