疑難排解
本文檔涵蓋從 Material UI v4 遷移至 v5 時已知的問題和常見問題。
Material UI v5 遷移
- 開始使用
- 重大變更第一部分:樣式與主題
- 重大變更第二部分:組件
- 從 JSS 遷移
- 疑難排解 👈 您在這裡
遷移至 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
而不是 @material-ui/core
。
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
此錯誤來自於 Fade
、Grow
、Slide
、Zoom
組件,原因是缺少 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 上的這個 issue。
[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'
@mui/material/colors/red
自 v1.0.0 以來被視為私有。要修正此錯誤,您必須替換導入。有關更多詳細資訊,請參閱 這個 GitHub issue。
我們建議使用這個 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>
範圍之外呼叫 useStyles
或 withStyles
時,會發生此錯誤,如下例所示
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')
此錯誤是由於嘗試存取空主題而產生的。
請確保您已解決以下問題
styled
應僅從@mui/material/styles
導入 (如果您未使用獨立的@mui/system
)
import { styled } from '@mui/material/styles';
useStyles
無法在<ThemeProvider>
之外呼叫。要解決此問題,請按照本節中的說明操作。
有關更多詳細資訊,請參閱 這個 GitHub issue。
仍然有問題?
如果您遇到此處未涵蓋的問題,請使用以下標題格式建立一個 GitHub issue:[Migration] 您的問題摘要。