跳转到内容

Troubleshooting

This document covers known issues and common problems encountered when migrating from Material UI v4 to v5.

Material UI v5 migration

  1. Getting started
  2. Breaking changes part one: style and theme
  3. Breaking changes part two: components
  4. Migrating from JSS
  5. Troubleshooting 👈 you are here

Styles broken after migrating to v5

There are two reasons why component styles may be broken after you've completed all steps in the migration process.

First, check if you have configured the StyledEngineProvider correctly, as shown in the Style library section.

If the StyledEngineProvider is already used at the top of your application and the styles are still broken, it may be the case that you still have @material-ui/core in your application.

This could be caused by other dependencies in the app that still rely on Material UI v4.

To check this, run npm ls @material-ui/core (or yarn why @material-ui/core). If your project contains such dependencies, you will see a list that looks something like this:

$ npm ls @material-ui/core
project@0.1.0 /path/to/project
└─┬  @mui/x-data-grid@4.0.0
  └── @material-ui/core@4.12.3

The output above indicates that @material-ui/core is a dependency of @mui/x-data-grid.

In this specific example, you would need to bump the version of @mui/x-data-grid to v5 so that it depends on @mui/material instead.

Storybook and Emotion

If your project uses Storybook v6.x, you will need to update the .storybook/main.js webpack config to use the most recent version of Emotion:

// .storybook/main.js

const path = require('path');
const toPath = (filePath) => path.join(process.cwd(), filePath);

module.exports = {
  webpackFinal: async (config) => {
    return {
      ...config,
      resolve: {
        ...config.resolve,
        alias: {
          ...config.resolve.alias,
          '@emotion/core': toPath('node_modules/@emotion/react'),
          'emotion-theming': toPath('node_modules/@emotion/react'),
        },
      },
    };
  },
};

Next, update .storybook/preview.js to prevent Storybook's Docs tab from displaying an empty page:

// .storybook/preview.js

import { ThemeProvider, createTheme } from '@mui/material/styles';
import { ThemeProvider as Emotion10ThemeProvider } from 'emotion-theming';

const defaultTheme = createTheme(); // or your custom theme

const withThemeProvider = (Story, context) => {
  return (
    <Emotion10ThemeProvider theme={defaultTheme}>
      <ThemeProvider theme={defaultTheme}>
        <Story {...context} />
      </ThemeProvider>
    </Emotion10ThemeProvider>
  );
};

export const decorators = [withThemeProvider];

// ...other storybook exports

Cannot read property scrollTop of null

This error comes from Fade, Grow, Slide, Zoom components due to a missing DOM node.

Make sure that the children forward the ref to the DOM for custom components:

// Ex. 1-1 ❌ This will cause an error because the Fragment is not a DOM node:
<Fade in>
  <React.Fragment>
    <CustomComponent />
  </React.Fragment>
</Fade>
// Ex. 1-2 ✅ Add a DOM node such as this div:
<Fade in>
  <div>
    <CustomComponent />
  </div>
</Fade>
// Ex. 2-1 ❌ This will cause an error because `CustomComponent` does not forward `ref` to the DOM:
function CustomComponent() {
  return <div>...</div>;
}

<Fade in>
  <CustomComponent />
</Fade>;
// Ex. 2-2 ✅ Add `React.forwardRef` to forward `ref` to the DOM:
const CustomComponent = React.forwardRef(function CustomComponent(props, ref) {
  return (
    <div ref={ref}>
      ...
    </div>
  )
})

<Fade in>
  <CustomComponent />
</Fade>

For more details, checkout this issue on GitHub.

[Types] Property "palette", "spacing" does not exist on type 'DefaultTheme'

This error arises because makeStyles is now exported from the @mui/styles package, which does not know about Theme in the core package.

To fix this, you need to augment the DefaultTheme (empty object) in @mui/styles with Theme from the core.

Read more about module augmentation in the official TypeScript docs.

TypeScript

Add this snippet to your theme file:

// it could be your App.tsx file or theme file that is included in your tsconfig.json
import { Theme } from '@mui/material/styles';

declare module '@mui/styles/defaultTheme' {
  // eslint-disable-next-line @typescript-eslint/no-empty-interface (remove this line if you don't have the rule enabled)
  interface DefaultTheme extends Theme {}
}

JavaScript

If you are using an IDE like VSCode which is able to infer types from a d.ts file, create index.d.ts in your src folder and add the following lines of code:

// index.d.ts
declare module '@mui/private-theming' {
  import type { Theme } from '@mui/material/styles';

  interface DefaultTheme extends Theme {}
}

[Jest] SyntaxError: Unexpected token 'export'

@mui/material/colors/red is considered private since v1.0.0. To fix this error, you must replace the import. For more details, see this GitHub issue.

We recommend using this codemod to fix all imports in your project:

npx @mui/codemod v5.0.0/optimal-imports <path>

You can fix it manually like this:

-import red from '@mui/material/colors/red';
+import { red } from '@mui/material/colors';

makeStyles - TypeError: Cannot read property 'drawer' of undefined

This error occurs when calling useStyles or withStyles outside of the scope of <ThemeProvider>, as in the following example:

import * as React from 'react';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import makeStyles from '@mui/styles/makeStyles';
import Card from '@mui/material/Card';
import CssBaseline from '@mui/material/CssBaseline';

const useStyles = makeStyles((theme) => ({
  root: {
    display: 'flex',
    backgroundColor: theme.palette.primary.main,
    color: theme.palette.common.white,
  },
}));

const theme = createTheme();

function App() {
  const classes = useStyles(); // ❌ called outside of ThemeProvider
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Card className={classes.root}>...</Card>
    </ThemeProvider>
  );
}

export default App;

You can fix this by moving useStyles inside another component so that it is called under <ThemeProvider>:

// ...imports

function AppContent(props) {
  const classes = useStyles(); // ✅ This is safe because it is called inside ThemeProvider
  return <Card className={classes.root}>...</Card>;
}

function App(props) {
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <AppContent {...props} />
    </ThemeProvider>
  );
}

export default App;

TypeError: Cannot read properties of undefined (reading 'pxToRem')

This error results from trying to access an empty theme.

Make sure that you have addressed the following issues:

  1. styled should only be imported from @mui/material/styles (if you are not using the standalone @mui/system):
import { styled } from '@mui/material/styles';
  1. useStyles cannot be called outside of <ThemeProvider>. To fix this problem, follow the instructions in this section.

For more details, see this GitHub issue.

Still having problems?

If you're encountering a problem not covered here, please create a GitHub issue with this title format: [Migration] Summary of your issue.