跳到内容
+

故障排除

本文档涵盖了从 Material UI v4 迁移到 v5 时遇到的已知问题和常见问题。

Material UI v5 迁移

  1. 开始使用
  2. 重大更改第一部分:样式和主题
  3. 重大更改第二部分:组件
  4. 从 JSS 迁移
  5. 故障排除 👈 你在这里

迁移到 v5 后样式损坏

在完成迁移过程中的所有步骤后,组件样式可能损坏的原因有两个。

首先,检查您是否已正确配置 StyledEngineProvider,如样式库部分所示。

如果 StyledEngineProvider 已在您的应用程序顶部使用,但样式仍然损坏,则可能是您的应用程序中仍然有 @material-ui/core

这可能是由应用程序中仍然依赖 Material UI v4 的其他依赖项引起的。

要检查这一点,请运行 npm ls @material-ui/core(或 yarn why @material-ui/core)。如果您的项目包含此类依赖项,您将看到如下列表

$ 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

上面的输出表明 @material-ui/core@mui/x-data-grid 的依赖项。

在这个具体的例子中,您需要将 @mui/x-data-grid 的版本提升到 v5,以便它依赖于 @mui/material

Storybook 和 Emotion

如果您的项目使用 Storybook v6.x,您需要更新 .storybook/main.js webpack 配置以使用最新版本的 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'),
        },
      },
    };
  },
};

接下来,更新 .storybook/preview.js 以防止 Storybook 的 Docs 选项卡显示空白页

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

无法读取 null 的属性 scrollTop

此错误来自 FadeGrowSlideZoom 组件,原因是缺少 DOM 节点。

确保子组件将 ref 转发到自定义组件的 DOM

// 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>

有关更多详细信息,请查看 GitHub 上的此问题

[Types] 属性 “palette”、“spacing” 在类型 “DefaultTheme” 上不存在

出现此错误的原因是 makeStyles 现在从 @mui/styles 包导出,该包不知道核心包中的 Theme

要解决此问题,您需要使用核心中的 Theme 扩充 @mui/styles 中的 DefaultTheme(空对象)。

阅读有关模块扩充的更多信息,请参阅官方 TypeScript 文档

TypeScript

将此代码片段添加到您的主题文件中

// 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

如果您正在使用像 VS Code 这样的 IDE,它可以从 d.ts 文件推断类型,请在您的 src 文件夹中创建 index.d.ts 并添加以下代码行

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

  interface DefaultTheme extends Theme {}
}

[Jest] SyntaxError: Unexpected token 'export'

自 v1.0.0 起,@mui/material/colors/red 被认为是私有的。要修复此错误,您必须替换导入。有关更多详细信息,请参阅此 GitHub 问题

我们建议使用此 codemod 来修复项目中的所有导入

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

您可以手动修复它,如下所示

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

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

当在 <ThemeProvider> 范围之外调用 useStyleswithStyles 时,会发生此错误,如下例所示

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;

您可以通过将 useStyles 移动到另一个组件内部来修复此问题,以便在 <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')

此错误是由于尝试访问空主题而导致的。

确保您已解决以下问题

  1. styled 应该只从 @mui/material/styles 导入(如果您未使用独立的 @mui/system
import { styled } from '@mui/material/styles';
  1. useStyles 不能在 <ThemeProvider> 之外调用。要解决此问题,请按照本节中的说明操作。

有关更多详细信息,请参阅此 GitHub 问题

仍然有问题?

如果您遇到此处未涵盖的问题,请创建 GitHub issue,标题格式为:[Migration] 您的 issue 摘要