cannot use default import in a component library
@mnajdova is already working on this.
Since Dec 20, 2022.
- Dominant language
- JavaScript
- Stars
- 99.1k
- Forks
- 32.5k
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 106
Description
Duplicates
- I have searched the existing issues
Latest version
- I have tested the latest version
Steps to reproduce 🕹
Link to live example:
Steps:
- create a basic lib component with this dummy component (with a default import):
import Paper from '@mui/material/Paper';
import React from 'react';
export interface DummyProps {
message: string;
}
const Dummy = ({ message }: DummyProps) => {
return (
<Paper>{message}</Paper>
);
};
export default Dummy;
-
Set @mui and @emotion as a peer dependency (see config file below)
-
rollup (see config below) and publish the lib
-
Create a simple react application, with a component SuperDummy using Dummy from the lib
-
Write a unit test using SuperDummy
=> the test should fail with an error like
React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
Current behavior 😯
On one side I have a component library using react, mui and emotion as peerDep.
package.json
"peerDependencies": {
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@mui/icons-material": "^5.10.15",
"@mui/material": "^5.10.15",
"react": "18.2.0",
"react-dom": "18.2.0"
}
rollup config (note the regexp for @emotion and @mui)
external: [
'react',
'react-dom',
/@emotion\/.*/,
/@mui\/.*/,
],
output: [
{
file: 'dist/index.cjs.min.js',
format: 'cjs',
sourcemap: true,
plugins: [terser()],
},
{
file: 'dist/index.esm.min.js',
format: 'esm',
sourcemap: true,
plugins: [terser()],
},
],
plugins: [
resolve({ browser: true }),
...
typescript({ tsconfig: './tsconfig.json' }),
],
},
Lib is published with npm.
On the other side, I have a simple react application (storybook, webpack5) Nothing special on the config on this side.
When I run storybook, it works fine.
When I run the app, it works fine too.
But when I run the jest unit tests, I get this error:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
I managed to surface that the error occurs as soon as I have a default import in the component library.
Like
import Paper from '@mui/material/Paper
instead of
import { Paper } from '@mui/material';
For those basic imports, I can leave with the second import, but then, I need to use icons too (or styled from @emotion/styled)
And these imports are only default:
import Circle from '@mui/icons-material/Circle';
As a workaround, I made this wrap and now it works but it's not ideal:
import Circle from '@mui/icons-material/Circle';
import { SvgIcon } from '@mui/material';
const normalizeIcon = (Icon: typeof SvgIcon) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
return ((Icon as any).default ? (Icon as any).default : Icon) as typeof SvgIcon;
};
const CircleIcon = normalizeIcon(Circle)`
Expected behavior 🤔
I would like to be able to use default imports without any error.
For instance:
import Circle from '@mui/icons-material/Circle';
Context 🔦
I will have several applications and I want to share theme and components. Hence the creation of the component library.
I want to be able to use the component library from the apps whatever the way the component library makes it's imports.
Your environment 🌎
npx @mui/envinfo
I used FireFox.
System:
OS: Linux 6.0 Fedora Linux 36 (Workstation Edition)
Binaries:
Node: 18.1.0 - /usr/bin/node
Yarn: Not Found
npm: 8.8.0 - /usr/bin/npm
Browsers:
Chrome: Not Found
Firefox: 107.0.1
npmPackages:
@emotion/react: ^11.10.5 => 11.10.5
@emotion/styled: ^11.10.5 => 11.10.5
@mui/base: 5.0.0-alpha.110
@mui/core-downloads-tracker: 5.11.0
@mui/icons-material: ^5.10.15 => 5.11.0
@mui/material: ^5.10.15 => 5.11.0
@mui/private-theming: 5.11.0
@mui/styled-engine: 5.11.0
@mui/system: 5.11.0
@mui/types: 7.2.3
@mui/utils: 5.11.0
@types/react: ^18.0.3 => 18.0.26
react: ^18.2.0 => 18.2.0
react-dom: ^18.2.0 => 18.2.0
typescript: ^4.6.3 => 4.9.4
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.