跳至內容
+

升級至 v7

本指南說明如何從 Material UI v6 升級至 v7。

為何您應該升級至 Material UI v7

改進的 ESM 支援

套件版面配置已更新,現在透過 package.json 中的 exports 欄位,明確地同時支援有效的 ESM 和 CommonJS。您可以在 Node.js 文件中閱讀更多關於套件匯出的資訊。

此更新修正了 Vite 和 webpack 等熱門打包工具的幾個問題,並使從 Node.js 下的 ES 模組載入 MUI 套件成為可能。

使用體驗改善

Material UI v7 具有其他使用體驗改善,包括

  • 所有組件中插槽模式的標準化
  • 透過用戶端應用程式的 StyledEngineProvider 中的 enableCssLayer 屬性,以及 Next.js App Router 應用程式的 AppRouterCacheProvider,支援 CSS 層疊
  • 移除已棄用的 API,以減少 API 介面並使文件更易於瀏覽

如果您正在使用任何這些套件,您也應該將它們的版本更新至 "7.0.0"

  • @mui/icons-material
  • @mui/system
  • @mui/lab
  • @mui/material-nextjs
  • @mui/styled-engine
  • @mui/styled-engine-sc
  • @mui/utils

請注意,MUI X 套件遵循與 Material UI 相同的版本控制策略。如果您正在使用以下任何套件,它們在升級過程中應保持不變

  • @mui/x-data-grid
  • @mui/x-data-grid-pro
  • @mui/x-data-grid-premium
  • @mui/x-date-pickers
  • @mui/x-date-pickers-pro
  • @mui/x-charts
  • @mui/x-tree-view
  • @mui/x-tree-view-pro

支援的瀏覽器和版本

最低 React 版本

最低支援的 React 版本為 v17.0.0(與 v6 相同)。如果您想升級 React,建議先完成 Material UI 的升級,然後再升級 React。

最低 TypeScript 版本

最低支援的 TypeScript 版本已從 v4.7 提高到 4.9。

對於 @types/react* 套件,請確保它們與您正在使用的 react 主要版本相同。如果需要,請使用以下程式碼片段更新您的專案(將 <version> 替換為您正在使用的 react 主要版本)

npm install @types/react@<version> @types/react-dom@<version>

重大變更

由於 v7 是一個新的主要版本,它包含一些影響公開 API 的變更。以下說明從 Material UI v6 移轉至 v7 需要採取的步驟。

套件版面配置已更新

套件版面配置已更新為使用 Node.js exports 欄位。這帶來了幾個變更

不再允許超過一層的深層匯入。例如

- import createTheme from '@mui/material/styles/createTheme';
+ import { createTheme } from '@mui/material/styles';

這從未獲得官方支援,但現在將受到打包工具和執行時期的限制。

若要使用現代捆綁包(不包含舊版瀏覽器支援以縮減捆綁包大小),您需要將您的打包工具設定為使用 "mui-modern" exports condition

// webpack.config.js
{
  resolve: {
    conditionNames: ['mui-modern', '...'],
  }
}

// vite.config.js
{
  resolve: {
    conditions: ['mui-modern', 'module', 'browser', 'development|production']
  }
}

如果您正在使用 Vite 別名來強制圖示套件的 ESM 匯入,您應該移除它,因為不再需要它

 // vite.config.js
   resolve: {
     alias: [
-      {
-        find: /^@mui\/icons-material\/(.*)/,
-        replacement: "@mui/icons-material/esm/$1",
-      },
     ],
   },

如果您正在擴充主題並使用巢狀匯入的宣告,您應該將它們替換為 @mui/material/styles。您可能還需要重新命名介面,因為有些介面是從 @mui/material/styles 以不同的名稱匯出的

-declare module '@mui/material/styles/createTypography' {
+declare module '@mui/material/styles' {
-  interface TypographyOptions {
+  interface TypographyVariantsOptions {
     // ...
   }

-  interface Typography {
+  interface TypographyVariants {
     // ...
   }
 }

Grid 和 Grid2 已重新命名

已棄用的 Grid 組件已重新命名為 GridLegacyGrid2 組件已移至 Grid 命名空間。根據您的專案,您可以遵循以下方法之一

  1. 如果您正在使用已棄用的 grid 並希望升級,請執行以下程式碼修改

    npx @mui/codemod v7.0.0/grid-props <path/to/folder>
    

    請參閱 Grid 升級指南以獲取更多資訊。

  2. 如果您正在使用已棄用的 grid 並希望繼續使用它,請如下更新 Grid 參考

     // imports
    -import Grid, { gridClasses, GridProps } from '@mui/material/Grid';
    +import Grid, { gridLegacyClasses, GridLegacyProps } from '@mui/material/GridLegacy';
    
    -import { Grid } from '@mui/material';
    +import { GridLegacy as Grid } from '@mui/material';
    
     // theme
     const theme = createTheme({
       components: {
    -    MuiGrid: {
    +    MuiGridLegacy: {
           // ...
         },
       },
     });
    
     // CSS classes
    -.MuiGrid-root
    +.MuiGridLegacy-root
    
  3. 如果您正在使用 Grid2,請如下更新 Grid2 參考

     // imports
    -import Grid, { grid2Classes as gridClasses, Grid2Props as GridProps } from '@mui/material/Grid2';
    +import Grid, { gridClasses, GridProps } from '@mui/material/Grid';
    
    -import { Grid2 as Grid } from '@mui/material';
    +import { Grid } from '@mui/material';
    
     // theme
     const theme = createTheme({
       components: {
    -    MuiGrid2: {
    +    MuiGrid: {
           // ...
         },
       },
     });
    
     // CSS classes
    -.MuiGrid2-root
    +.MuiGrid-root
    

InputLabel size 屬性已標準化

InputLabelsize 屬性現在遵循在其他組件(如 ButtonTextField)中使用的標準命名慣例。為了保持一致性,'normal' 已替換為 'medium'

如果您之前使用 size="normal",請將其更新為 size="medium"

-<InputLabel size="normal">Label</InputLabel>
+<InputLabel size="medium">Label</InputLabel>

預設行為保持不變,因此除非您明確設定 size="normal",否則無需更新。

使用此程式碼修改自動更新 size

npx @mui/codemod v7.0.0/input-label-size-normal-medium <path/to/folder>

SvgIcon 的 data-testid 已移除

預設的 data-testid 屬性已從生產捆綁包中的 @mui/icons-material 圖示中移除。此變更確保 data-testid 屬性僅在需要時定義,從而減少命名衝突的可能性並移除生產環境中不必要的屬性。

主題行為變更

當啟用 CSS 主題變數以及內建的明亮和黑暗色彩配置時,主題不再在模式之間變更。以下程式碼片段示範了當使用者切換深色模式時的此行為,useColorScheme 中的 mode 狀態會變更,但主題物件不再變更

import {
  ThemeProvider,
  createTheme,
  useTheme,
  useColorScheme,
} from '@mui/material/styles';

const theme = createTheme({
  cssVariables: {
    colorSchemeSelector: 'class',
  },
  colorSchemes: {
    light: true,
    dark: true,
  },
});
console.log(theme.palette.mode); // 'light' is the default mode

function ColorModeToggle() {
  const { setMode, mode } = useColorScheme();
  const theme = useTheme();

  React.useEffect(() => {
    console.log(mode); // logged 'light' at first render, and 'dark' after the button click
  }, [mode]);

  React.useEffect(() => {
    console.log(theme.palette.mode); // logged 'light' at first render, no log after the button click
  }, [theme]);

  return <button onClick={() => setMode('dark')}>Toggle dark mode</button>;
}

function App() {
  return (
    <ThemeProvider theme={theme}>
      <ColorModeToggle />
    </ThemeProvider>
  );
}

此預設行為旨在透過避免在模式變更時不必要的重新渲染來提高效能。

建議在您的樣式中使用 theme.vars.* 作為值,以直接參考 CSS 變數

const Custom = styled('div')(({ theme }) => ({
  color: theme.vars.palette.text.primary,
  background: theme.vars.palette.primary.main,
}));

如果您需要執行執行時期計算,我們建議盡可能使用 CSS 而不是 JavaScript。例如,可以使用 color-mix 函數調整顏色的 alpha 通道

const Custom = styled('div')(({ theme }) => ({
  color: `color-mix(in srgb, ${theme.vars.palette.text.primary}, transparent 50%)`,
}));

但是,如果 CSS 方法不可行,您可以直接從 theme.colorSchemes 物件存取值,然後同時套用明亮和黑暗樣式

const Custom = styled('div')(({ theme }) => ({
  color: alpha(theme.colorSchemes.light.palette.text.primary, 0.5),
  ...theme.applyStyles('dark', {
    color: alpha(theme.colorSchemes.dark.palette.text.primary, 0.5),
  }),
}));

如果以上任何方法都不適合您的專案,您可以透過將 forceThemeRerender 屬性傳遞給 ThemeProvider 組件來停用此行為

<ThemeProvider forceThemeRerender />

已移除已棄用的 API

在 v5 中已棄用的 API 已在 v7 中移除。

createMuiTheme 函數

已棄用的 createMuiTheme 函數已移除。請改用 createTheme

-import { createMuiTheme } from '@mui/material/styles';
+import { createTheme } from '@mui/material/styles';

Dialog 的 onBackdropClick 屬性

已棄用的 onBackdropClick 屬性已從 Dialog 組件中移除。請改用 onClose 回呼,它會接收事件和對話框關閉的原因。以下是如何使用它的範例

function Example() {
  const [open, setOpen] = React.useState(false);

  const handleClose = (event, reason) => {
    if (reason === 'backdropClick') {
      // Handle the backdrop click
    }
    setOpen(false);
  };

  return (
    <Dialog open={open} onClose={handleClose}>
      {/* Dialog content */}
    </Dialog>
  );
}

experimentalStyled 函數

已棄用的 experimentalStyled 函數已移除。請改用 styled

-import { experimentalStyled as styled } from '@mui/material/styles';
+import { styled } from '@mui/material/styles';

Hidden 和 PigmentHidden 組件

已棄用的 HiddenPigmentHidden 組件已移除。

使用 sx 屬性來替換 implementation="css"

-<Hidden implementation="css" xlUp><Paper /></Hidden>
+<Paper sx={{ display: { xl: 'none', xs: 'block' } }} />
-<Hidden implementation="css" mdDown><Paper /></Hidden>
+<Paper sx={{ display: { xs: 'none', md: 'block' } }} />

使用 useMediaQuery hook 來替換 implementation="js"

-<Hidden implementation="js" xlUp><Paper /></Hidden>
+const hidden = useMediaQuery(theme => theme.breakpoints.up('xl'));
+return hidden ? null : <Paper />;

Modal 的 onBackdropClick 屬性

已棄用的 onBackdropClick 屬性已從 Modal 組件中移除。請改用 onClose 回呼,它會接收事件和 modal 關閉的原因。以下是如何使用它的範例

function Example() {
  const [open, setOpen] = React.useState(false);

  const handleClose = (event, reason) => {
    if (reason === 'backdropClick') {
      // Handle the backdrop click
    }
    setOpen(false);
  };

  return (
    <Modal open={open} onClose={handleClose}>
      {/* Modal content */}
    </Modal>
  );
}

Rating 的 MuiRating-readOnly CSS 類別

已棄用的 MuiRating-readOnly 類別已移除,改用 Mui-readOnly 全域類別。

-.MuiRating-readOnly
+.Mui-readOnly

StepButtonIcon 型別

已棄用的 StepButtonIcon 型別已移除。請改用 StepButtonProps['icon']

- import { StepButtonIcon } from '@mui/material/StepButton';
+ import { StepButtonProps } from '@mui/material/StepButton';

-StepButtonIcon
+StepButtonProps['icon']

StyledEngineProvider 匯入路徑

'@mui/material' 匯入 StyledEngineProvider 已被棄用,現在已被移除。請改從 '@mui/material/styles' 匯入

-import { StyledEngineProvider } from '@mui/material';
+import { StyledEngineProvider } from '@mui/material/styles';

Lab 組件已移至主套件

以下 @mui/lab 組件和 hook 已移至 @mui/material

  • Alert
  • AlertTitle
  • Autocomplete
  • AvatarGroup
  • Pagination
  • PaginationItem
  • Rating
  • Skeleton
  • SpeedDial
  • SpeedDialAction
  • SpeedDialIcon
  • ToggleButton
  • ToggleButtonGroup
  • usePagination

若要繼續使用這些組件和 hook,請從 @mui/material 而不是 @mui/lab 匯入它們。

-import Alert from '@mui/lab/Alert';
+import Alert from '@mui/material/Alert';

-import { Alert } from '@mui/lab';
+import { Alert } from '@mui/material';

使用此程式碼修改自動更新匯入

npx @mui/codemod v7.0.0/lab-removed-components <path/to/folder>