mui / mui/material-ui

cannot use default import in a component library

Open
#35,535 7 comments 2 reactions 1 assignee View on GitHub

@mnajdova is already working on this.

Since Dec 20, 2022.

scope: all components
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:

  1. 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;
  1. Set @mui and @emotion as a peer dependency (see config file below)

  2. rollup (see config below) and publish the lib

  3. Create a simple react application, with a component SuperDummy using Dummy from the lib

  4. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.