material-ui: React "each child in a list should have a unique key" error when bundling MUI

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

bundling mui in production mode generates key errors for seemingly no reason

Expected behavior 🤔

bundling mui in production mode does not generate key errors for components that arent actually part of a list

Steps to reproduce 🕹

Steps:

  1. To reproduce the error, clone this minimal reproduction to your local machine and then npm ci to load the dependencies.
  2. Next, run npm run build:prod to create a production bundle
  3. Use npm link to run the library against a fresh React app via Create-react-app or something similar.
  4. Within your fresh React application, just import the Tooltip and/or Checkbox components from this library while linked and then render them to the page. You will see the react errors.
  5. While linked, you can then run npm run build:dev to generate a development build. The Tooltip and Checkbox in you React app should no longer throw the unique key errors in the console.

Context 🔦

my team manages an internal component library that is based on mui and gets consumed by all other frontend developers at my job. This component library imports MUI components/helpers and makes any modifications needed, and then exports all of the modified stuff as well as all of the unmodified MUI functions (think export * from @mui/material basically).

What we’ve been doing is bundling mui into our component library at build time, that way consuming applications just install our component library, rather than having to install our component library + a bunch of MUI peer dependencies. However, we noticed that when we publish the production build of our component library, certain components such as the Tooltip and Checkbox will throw “each child in a list should have a unique key” warnings once they’re imported and used in our applications.

Initially we thought this was an issue with our custom components or maybe our build chain, but I was able to recreate the problem by just making a brand new npm package, importing and then re-exporting all the MUI stuff and building the npm package in production mode. I then used npm link to run the package in a fresh Create React App and the Checkbox + Tooltip components immediately threw the key warnings. image image

Is this intended behavior and/or is this documented anywhere? Are we just supposed to build a development bundle instead? Ultimately our goal is to be able to bundle mui into our company’s internal component library so that the component library maintainers can control the version of things and consumers can simply rely on importing our package

Your environment 🌎

npx @mui/envinfo

Unfortunately the npx @mui/envinfo command doesnt seem to be working for me?? I attempt to execute it and it just hangs on the CLI. I am using Node 14 on macOs monterrey

image

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 3
  • Comments: 15 (7 by maintainers)

Most upvoted comments

Thanks @lancej1022 for the useful reproduction and easy-to-follow steps, it was really helpful. Also thanks @Coreen-Cooper for finding out that cloneElement was the origin.

The issue can be solved by modifying the webpack config like this:

-const externals = {};

-Object.keys(pkg.peerDependencies).forEach((dep) => {
-  externals[dep] = dep;
-});

+const externals = new RegExp(
+  `^(?:${Object.keys(pkg.peerDependencies).join("|")})(?:/.*)?$`
+);

After this change, the externals config becomes /^(?:date-fns|react|react-dom)(?:\/.*)?$/. As you can see, the peer dependencies subpaths are also included in the externals, as they should. In particular react/jsx-runtime was the one that was missing, so it was being bundled even though it shouldn’t.

You can check the difference this config change makes in this diff check: https://www.diffchecker.com/A143le9a/

I haven’t dug deep enough to understand why this caused cloneElement to throw the error. The bottom line is React doesn’t work properly when multiple versions of it or one of its dependencies are loaded simultaneusly.

As this is an issue various people stumbled upon, before closing it I will come up with some further actions to try to avoid it in the future and will post those here when I have them.

The same warning appears using FocusTrap. I believe the issue originates at: image

Although it is not an ideal solution since a list is not being rendered, passing in a key eliminates the warning for all instances of the FocusTrap:

{

      {React.cloneElement(children, { ref: handleRef, onFocus, key:"some-key" })}
}

This could be the same issue with Tooltip which uses React clone element: image

React.cloneElement image

Sorry, I can’t offer a solution, but I hope this is helpful.

Any progress on this? Experiencing the same issue.