跳到內容
+

v5 版本中的重大變更,第一部分:樣式與主題

這是一份關於 Material UI v5 中引入的重大變更以及如何從 v4 遷移的參考指南。本部分涵蓋樣式和主題的變更。

Material UI v5 遷移

  1. 開始使用
  2. 重大變更第一部分:樣式與主題 👈 您在這裡
  3. 重大變更第二部分:元件
  4. 從 JSS 遷移
  5. 疑難排解

重大變更,第一部分

Material UI v5 從 v4 引入了許多重大變更。許多這些變更可以使用 程式碼修改 (codemods) 自動解決,詳情請參閱主要遷移指南

以下文件列出了 v5 中與樣式和主題相關的所有重大變更以及如何解決這些變更。

完成此處的步驟後,請繼續前往v5 版本中的重大變更,第二部分:元件,以繼續遷移流程。

將主題 styleOverrides 遷移至 Emotion

重構本機規則參考

儘管您在主題中定義的樣式覆寫可能部分有效,但在樣式化巢狀元素的方式上存在重要差異。

與 JSS 一起使用的 $ 語法 (本機規則參考) 不適用於 Emotion。您需要將這些選取器替換為有效的類別選取器。

替換狀態類別名稱

 const theme = createTheme({
   components: {
     MuiOutlinedInput: {
       styleOverrides: {
         root: {
-          '&$focused': {
+          '&.Mui-focused': {
             borderWidth: 1,
           }
         }
       }
     }
   }
 });

將巢狀類別選取器替換為全域類別名稱

 const theme = createTheme({
   components: {
     MuiOutlinedInput: {
       styleOverrides: {
         root: {
-          '& $notchedOutline': {
+          '& .MuiOutlinedInput-notchedOutline': {
             borderWidth: 1,
           }
         }
       }
     }
   }
 });
+import { outlinedInputClasses } from '@mui/material/OutlinedInput';

 const theme = createTheme({
   components: {
     MuiOutlinedInput: {
       styleOverrides: {
         root: {
-          '& $notchedOutline': {
+          [`& .${outlinedInputClasses.notchedOutline}`]: {
             borderWidth: 1,
           }
         }
       }
     }
   }
 });

請查看完整的可用全域狀態類別名稱清單

重構空格和逗號分隔值的替代語法

Emotion 不支援 JSS 支援的空格和逗號分隔值的替代、基於陣列的語法。

將基於陣列的值替換為基於字串的值

之前

const theme = createTheme({
  overrides: {
    MuiBox: {
      root: {
        background: [
          ['url(image1.png)', 'no-repeat', 'top'],
          ['url(image2.png)', 'no-repeat', 'center'],
          '!important',
        ],
      },
    },
  },
});

之後

const theme = createTheme({
  components: {
    MuiBox: {
      styleOverrides: {
        root: {
          background:
            'url(image1.png) no-repeat top, url(image2.png) no-repeat center !important',
        },
      },
    },
  },
});

請務必根據需要為數值新增單位。

之前

const theme = createTheme({
  overrides: {
    MuiOutlinedInput: {
      root: {
        padding: [[5, 8, 6]],
      },
    },
  },
});

之後

const theme = createTheme({
  components: {
    MuiOutlinedInput: {
      styleOverrides: {
        root: {
          padding: '5px 8px 6px',
        },
      },
    },
  },
});

ref

重構非 ref 轉發類別元件

已移除在 component 屬性或作為直接 children 中對非 ref 轉發類別元件的支援。

如果您使用的是 unstable_createStrictModeTheme 或未看到任何與 React.StrictMode 中的 findDOMNode 相關的警告,則您無需採取任何進一步的動作。

否則,請查看組合指南中的關於 refs 的注意事項章節,以了解如何遷移。此變更幾乎影響所有您使用 component 屬性或將 children 傳遞給需要 children 為元素的元件 (例如 <MenuList><CustomMenuItem /></MenuList>) 的情況。

修正 ref 類型特異性

對於某些元件,當傳遞 ref 時,您可能會收到類型錯誤。為了避免錯誤,您應該使用特定的元素類型。例如,Card 預期 ref 的類型為 HTMLDivElement,而 ListItem 預期其 ref 類型為 HTMLLIElement

以下是一個範例

 import * as React from 'react';
 import Card from '@mui/material/Card';
 import ListItem from '@mui/material/ListItem';

 export default function SpecificRefType() {
-  const cardRef = React.useRef<HTMLElement>(null);
+  const cardRef = React.useRef<HTMLDivElement>(null);

-  const listItemRef = React.useRef<HTMLElement>(null);
+  const listItemRef = React.useRef<HTMLLIElement>(null);
   return (
     <div>
       <Card ref={cardRef}></Card>
       <ListItem ref={listItemRef}></ListItem>
     </div>
   );
 }

以下是每個元件預期的特定元素類型

@mui/material

@mui/lab

樣式函式庫

✅ 調整 CSS 注入順序

v5 中預設使用的樣式函式庫是 Emotion

如果您使用 JSS 來覆寫 Material UI 元件的樣式 (例如,由 makeStyles 建立的樣式),則您需要注意 CSS 注入順序。JSS <style> 元素需要在 Emotion <style> 元素之後注入到 <head> 中。

若要執行此操作,您需要在元件樹狀結構的頂端使用具有 injectFirst 選項的 StyledEngineProvider,如下所示

import * as React from 'react';
import { StyledEngineProvider } from '@mui/material/styles';

export default function GlobalCssPriority() {
  return (
    {/* Inject Emotion before JSS */}
    <StyledEngineProvider injectFirst>
      {/* Your component tree. Now you can override Material UI's styles. */}
    </StyledEngineProvider>
  );
}

✅ 將 prepend 新增至 createCache

如果您有自訂快取並且使用 Emotion 來樣式化您的應用程式,它將覆寫 Material UI 提供的快取。

若要修正注入順序,請將 prepend 選項新增至 createCache,如下所示

 import * as React from 'react';
 import { CacheProvider } from '@emotion/react';
 import createCache from '@emotion/cache';

 const cache = createCache({
   key: 'css',
+  prepend: true,
 });

 export default function PlainCssPriority() {
   return (
     <CacheProvider value={cache}>
       {/* Your component tree. Now you can override Material UI's styles. */}
     </CacheProvider>
   );
 }

主題結構

✅ 新增 adaptV4Theme helper

主題的結構在 v5 中已變更。您需要更新其形狀。為了更順暢地轉換,adaptV4Theme helper 允許您迭代地將一些主題變更升級到新的主題結構。

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

-const theme = createMuiTheme({
+const theme = createTheme(adaptV4Theme({
   // v4 theme
-});
+}));

適配器支援以下變更

移除 gutters

"gutters" 抽象概念尚未證明其使用頻率足以使其有價值。

-theme.mixins.gutters(),
+paddingLeft: theme.spacing(2),
+paddingRight: theme.spacing(2),
+[theme.breakpoints.up('sm')]: {
+  paddingLeft: theme.spacing(3),
+  paddingRight: theme.spacing(3),
+},

✅ 移除 px 後綴

theme.spacing 現在預設傳回帶有 px 單位的單一值。此變更改善了與 styled-components 和 Emotion 的整合。

之前

theme.spacing(2) => 16

之後

theme.spacing(2) => '16px'

✅ 重新命名 theme.palette.type

theme.palette.type 鍵已重新命名為 theme.palette.mode,以更好地遵循通常用於描述此功能的「深色模式」術語。

 import { createTheme } from '@mui/material/styles';
-const theme = createTheme({ palette: { type: 'dark' } }),
+const theme = createTheme({ palette: { mode: 'dark' } }),

變更預設 theme.palette.info 顏色

預設的 theme.palette.info 顏色已變更為在淺色和深色模式下都通過 AA 無障礙標準對比度。

  info = {
-  main: cyan[500],
+  main: lightBlue[700], // lightBlue[400] in "dark" mode

-  light: cyan[300],
+  light: lightBlue[500], // lightBlue[300] in "dark" mode

-  dark: cyan[700],
+  dark: lightBlue[900], // lightBlue[700] in "dark" mode
  }

變更預設 theme.palette.success 顏色

預設的 theme.palette.success 顏色已變更為在淺色和深色模式下都通過 AA 無障礙標準對比度。

  success = {
-  main: green[500],
+  main: green[800], // green[400] in "dark" mode

-  light: green[300],
+  light: green[500], // green[300] in "dark" mode

-  dark: green[700],
+  dark: green[900], // green[700] in "dark" mode
  }

變更預設 theme.palette.warning 顏色

預設的 theme.palette.warning 顏色已變更為在淺色和深色模式下都通過 AA 無障礙標準對比度。

  warning = {
-  main: orange[500],
+  main: '#ED6C02', // orange[400] in "dark" mode

-  light: orange[300],
+  light: orange[500], // orange[300] in "dark" mode

-  dark: orange[700],
+  dark: orange[900], // orange[700] in "dark" mode
  }

還原 theme.palette.text.hint 鍵 (如果需要)

theme.palette.text.hint 鍵在 Material UI 元件中未使用,並且已移除。如果您依賴它,您可以將其重新新增

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

-const theme = createTheme(),
+const theme = createTheme({
+  palette: { text: { hint: 'rgba(0, 0, 0, 0.38)' } },
+});

重新建構元件定義

主題中的元件定義已在 components 鍵下重新建構,使其更容易找到。

1. props

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

 const theme = createTheme({
-  props: {
-    MuiButton: {
-      disableRipple: true,
-    },
-  },
+  components: {
+    MuiButton: {
+      defaultProps: {
+        disableRipple: true,
+      },
+    },
+  },
 });

2. overrides

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

 const theme = createTheme({
-  overrides: {
-    MuiButton: {
-      root: { padding: 0 },
-    },
-  },
+  components: {
+    MuiButton: {
+      styleOverrides: {
+        root: { padding: 0 },
+      },
+    },
+  },
 });

@mui/styles

更新 ThemeProvider 匯入

如果您將 @mui/styles 中的公用程式與 @mui/material 一起使用,則應將 @mui/styles 中的 ThemeProvider 用法替換為從 @mui/material/styles 匯出的用法。

這樣,在上下文中提供的主題將在從 @mui/styles 匯出的樣式公用程式 (例如 makeStyleswithStyles 等) 以及 Material UI 元件中都可用。

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

請務必在應用程式的根目錄中新增 ThemeProvider,因為 defaultTheme 在來自 @mui/styles 的公用程式中不再可用。

✅ 為 DefaultTheme 新增模組擴充 (TypeScript)

@mui/styles 套件不再是 @mui/material/styles 的一部分。

如果您將 @mui/styles@mui/material 一起使用,則需要為 DefaultTheme 新增模組擴充。

// in the file where you are creating the theme (invoking the function `createTheme()`)
import { Theme } from '@mui/material/styles';

declare module '@mui/styles' {
  interface DefaultTheme extends Theme {}
}

@mui/material/colors

✅ 變更顏色匯入

超過一級的巢狀匯入是私有的。例如,您不能再從 @mui/material/colors/red 匯入 red

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

@mui/material/styles

✅ 將 fade 重新命名為 alpha

fade() 已重新命名為 alpha(),以更好地描述其功能。

先前的名稱在輸入顏色已具有 alpha 值時會造成混淆。helper 會覆寫顏色的 alpha 值。

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

  const classes = makeStyles(theme => ({
-  backgroundColor: fade(theme.palette.primary.main, theme.palette.action.selectedOpacity),
+  backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
  }));

✅ 更新 createStyles 匯入

來自 @mui/material/stylescreateStyles 函式已移至從 @mui/styles 匯出的函式。這對於移除 Material UI npm 套件中對 @mui/styles 的依賴性是必要的。

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

✅ 更新 createGenerateClassName 匯入

createGenerateClassName 函式不再從 @mui/material/styles 匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles 套件匯入它。

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

若要在不使用 @mui/styles 的情況下產生自訂類別名稱,請查看 ClassName Generator 以了解更多詳細資訊。

✅ 重新命名 createMuiTheme

函式 createMuiTheme 已重新命名為 createTheme(),使其更直覺地與 ThemeProvider 一起使用。

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

-const theme = createMuiTheme({
+const theme = createTheme({

✅ 更新 MuiThemeProvider 匯入

MuiThemeProvider 元件不再從 @mui/material/styles 匯出。請改用 ThemeProvider

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

✅ 更新 jssPreset 匯入

jssPreset 物件不再從 @mui/material/styles 匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles 套件匯入它。

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

✅ 更新 makeStyles 匯入

由於 Material UI v5 不使用 JSS,因此基於 JSS 的 makeStyles 公用程式不再由 @mui/material/styles 匯出。在將您的應用程式從 JSS 遷移出來時,您可以暫時從 @mui/styles/makeStyles 匯入此已棄用的公用程式,然後再進一步重構您的元件。

請務必在應用程式的根目錄中新增 ThemeProvider,因為 defaultTheme 不再可用。

如果您將此公用程式與 @mui/material 一起使用,建議您改用 @mui/material/styles 中的 ThemeProvider 元件。

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

+const theme = createTheme();
  const useStyles = makeStyles((theme) => ({
    background: theme.palette.primary.main,
  }));
  function Component() {
    const classes = useStyles();
    return <div className={classes.root} />
  }

  // In the root of your app
  function App(props) {
-  return <Component />;
+  return <ThemeProvider theme={theme}><Component {...props} /></ThemeProvider>;
  }

✅ 更新 ServerStyleSheets 匯入

ServerStyleSheets 元件不再從 @mui/material/styles 匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles 套件匯入它。

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

styled

由於 Material UI v5 不使用 JSS,因此由 @mui/material/styles 匯出的基於 JSS 的 styled 公用程式已替換為等效的基於 Emotion 的公用程式,該公用程式不向後相容。在將您的應用程式從 JSS 遷移出來時,您可以暫時從已棄用的 @mui/styles 套件匯入基於 JSS 的公用程式,然後再進一步重構您的元件。

請務必在應用程式的根目錄中新增 ThemeProvider,因為 defaultTheme 不再可用。

如果您將此公用程式與 @mui/material 一起使用,建議您改用 @mui/material/styles 中的 ThemeProvider 元件。

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

+const theme = createTheme();
  const MyComponent = styled('div')(({ theme }) => ({ background: theme.palette.primary.main }));

  function App(props) {
-  return <MyComponent />;
+  return <ThemeProvider theme={theme}><MyComponent {...props} /></ThemeProvider>;
  }

✅ 更新 StylesProvider 匯入

StylesProvider 元件不再從 @mui/material/styles 匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles 套件匯入它。

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

✅ 更新 useThemeVariants 匯入

useThemeVariants Hook 不再從 @mui/material/styles 匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles 套件匯入它。

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

✅ 更新 withStyles 匯入

由於 Material UI v5 不使用 JSS,因此基於 JSS 的 withStyles 公用程式不再由 @mui/material/styles 匯出。在將您的應用程式從 JSS 遷移出來時,您可以暫時從 @mui/styles/withStyles 匯入此已棄用的公用程式,然後再進一步重構您的元件。

請務必在應用程式的根目錄中新增 ThemeProvider,因為 defaultTheme 不再可用。

如果您將此公用程式與 @mui/material 一起使用,則應改用 @mui/material/styles 中的 ThemeProvider 元件。

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

+const defaultTheme = createTheme();
  const MyComponent = withStyles((props) => {
    const { classes, className, ...other } = props;
    return <div className={clsx(className, classes.root)} {...other} />
  })(({ theme }) => ({ root: { background: theme.palette.primary.main }}));

  function App() {
-  return <MyComponent />;
+  return <ThemeProvider theme={defaultTheme}><MyComponent /></ThemeProvider>;
  }

✅ 將 innerRef 替換為 ref

innerRef 屬性替換為 ref 屬性。Refs 現在會自動轉發到內部元件。

  import * as React from 'react';
  import { withStyles } from '@mui/styles';

  const MyComponent = withStyles({
    root: {
      backgroundColor: 'red',
    },
  })(({ classes }) => <div className={classes.root} />);

  function MyOtherComponent(props) {
    const ref = React.useRef();
-  return <MyComponent innerRef={ref} />;
+  return <MyComponent ref={ref} />;
  }

更新 withTheme 匯入

withTheme HOC 公用程式已從 @mui/material/styles 套件中移除。您可以改用 @mui/styles/withTheme

請務必在應用程式的根目錄中新增 ThemeProvider,因為 defaultTheme 不再可用。

如果您將此公用程式與 @mui/material 一起使用,建議您改用 @mui/material/styles 中的 ThemeProvider 元件。

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

+const theme = createTheme();
  const MyComponent = withTheme(({ theme }) => <div>{theme.direction}</div>);

  function App(props) {
-  return <MyComponent />;
+  return <ThemeProvider theme={theme}><MyComponent {...props} /></ThemeProvider>;
  }

✅ 移除 withWidth

此 HOC 已移除。如果您需要此功能,可以嘗試使用 useMediaQuery Hook 的替代方案

@mui/icons-material

縮小 GitHub 圖示大小

GitHub 圖示的大小已從 24px 寬縮小為 22px 寬,以符合其他圖示的大小。

@material-ui/pickers

我們有一個專門頁面用於將 @material-ui/pickers 遷移至 v5。

系統

✅ 重新命名 gap 屬性

以下系統函式和屬性已重新命名,因為它們被視為已棄用的 CSS

  • gridGap 變為 gap
  • gridRowGap 變為 rowGap
  • gridColumnGap 變為 columnGap

✅ 將間距單位新增至 gap 屬性

gaprowGapcolumnGap 中使用間距單位。如果您先前使用的是數字,則需要提及 px 以繞過使用 theme.spacing 的新轉換。

  <Box
-  gap={2}
+  gap="2px"
  >

css 屬性替換為 sx,以避免與 styled-components 和 Emotion 的 css 屬性發生衝突。

-<Box css={{ color: 'primary.main' }} />
+<Box sx={{ color: 'primary.main' }} />