如何在 Material UI 5 中使用 useTheme?



我刚开始使用Material UI 5.0.4(带有styled-components),我想在组件中访问主题。我在网上看了看,看到了useTheme,所以我检查了文档并找到了它 -@mui/styles/useTheme.但是,它是旧文档,MUI 5 中不存在@mui/styles文档。因此,我查看了@mui/system,并找到了"访问组件中的主题"部分。但是,这只是指向旧文档!

在文档似乎对我没有帮助之后,我决定使用Visual Studio Code的"快速修复"功能,如果您将鼠标悬停在函数上,VSCode将为您提供要导入的选项列表。以下是我尝试过的选项列表,以及它们不起作用的原因:

  • @mui/material/styles/useTheme- 无论如何都返回默认主题对象。查看源代码,这就是它所做的 - 它切换到默认主题,然后返回主题。
  • @mui/material/private-theming/useTheme- 这只会返回null.我觉得我无论如何都不应该访问这个(它说private-),但我还是尝试过。
  • @mui/system/useTheme- 这就是我希望能奏效的。然而,这也可能是最奇怪的一个。它为我提供了默认主题,但它排除了许多属性。例如,它只提供palette.mode,除此之外palette没有其他键。(你可以在下面看到整个事情)
{
"breakpoints": {
"keys": ["xs", "sm", "md", "lg", "xl"],
"values": { "xs": 0, "sm": 600, "md": 900, "lg": 1200, "xl": 1536 },
"unit": "px"
},
"direction": "ltr",
"components": {},
"palette": { "mode": "light" },
"shape": { "borderRadius": 4 }
}
  • styled-components/useTheme- 返回undefined
  • @mui/styled-engine-sc/useTheme- 返回undefined.(我有一种感觉,这和styled-components/useTheme是一样的。

这些都是VSCode可以给我的建议,除了@mui/system/useTheme@mui/system/useTheme/useTheme之类的东西(这是一回事)。我也尝试过谷歌搜索东西,但它总是很旧,比如:

  • GitHub 上的问题 #8958 for MUI 引用了 v4 而不是 v5 中的@material-ui/core/styles
  • 标记为"从外部 material-ui 组件访问主题"的 SO 问题,它引用了旧文档(@material-ui/styles不再存在,并且@mui/material/styles/useTheme无法如上所述工作)

如果有人知道,请问如何在MUI 5的组件中获取主题?

事实证明,正确的useTheme@mui/material/styles/useTheme,并且您不能在执行ThemeProvider的同一组件中使用useTheme。例如,这个:

const App = () => {
const theme = useTheme();
return (
<ThemeProvider theme={myTheme}>
<Box bgcolor={theme.palette.background.default} width={100} height={100} />
</ThemeProvider>
);
};

将无法正常工作。但是,这:

const MyComponent = () => {
const theme = useTheme();
return <Box bgcolor={theme.palette.background.default} width={100} height={100} />;
};
const App = () => (
<ThemeProvider theme={myTheme}>
<MyComponent />
</ThemeProvider>
)

将正常工作,因为useTheme在单独的组件中使用。

以防万一有人想知道为什么useTheme你不能在与ThemeProvider,这是因为useTheme必须位于由ThemeProvider包装的组件中。上下文不适用于该组件树之外的组件。

对于任何仍在为此苦苦挣扎的人,我通过直接从@mui/material导入createThemeThemeProvideruseTheme来让它工作......

主题.js:

import { createTheme } from '@mui/material';
export const theme = createTheme({
...
});

_app.tsx (我正在使用下一个.js)

import { CssBaseline, ThemeProvider } from '@mui/material';
import type { AppProps } from 'next/app';
import React from 'react';
import { theme } from '../theme';
function MyApp({ Component, pageProps }: AppProps) {
return (
<React.StrictMode>
<CssBaseline />
<ThemeProvider theme={theme}>
<Component {...pageProps} />
</ThemeProvider>
</React.StrictMode>
);
}
export default MyApp;

navigation.tsx (my component with useTheme)

import { Drawer, useTheme } from '@mui/material';
import React from 'react';
const Navigation = (): JSX.Element => {
const theme = useTheme();
const drawerSx = {
'& .MuiDrawer-paper': {
background: `linear-gradient(to bottom right, ${theme.palette.primary.main}, ${theme.palette.primary.dark})`,
},
};
return (
<Drawer sx={drawerSx} variant="permanent">
...
</Drawer>
);
};
export default Navigation;

在我这样做之前,我一直在挣扎,它只应用默认主题,而不是自定义主题。

如果您使用的是@mui/material/styles的 useTheme 并且仍然无法正常工作,请检查您是否取消了 AppTheme.jsx(或您使用 ThemeProvider 的位置),请检查您是否正在使用@mui/material/styles的主题提供程序,而不是@emotion/react的主题提供程序。这就是为什么在我的情况下(使用 MUI v5)useTheme 不适用于我自己的主题(特别是我的自定义断点)。

如前所述,useTheme的第一次使用必须包含在父组件的ThemeProvider内。 (useTheme需要一个主题提供程序来借鉴。

从技术上讲,您可以useThemeThemeProvider相同的组件,只要该组件用于用ThemeProvider包装它的父组件 例:

const InnerComponent = () => {
// Use the theme from `App` below
const appTheme = useTheme();
// Local Theme. (May want to wrap with `useMemo` too.)
const innerTheme = createThemeV5(appTheme, {
// Local theme overrides
});
return (
<ThemeProvider theme={innerTheme}>
<Box />
</ThemeProvider>
);
}
const App = () => {
return (
<ThemeProvider theme={myTheme}>
<InnerComponent />
</ThemeProvider>
);
};

相关内容

  • 没有找到相关文章

最新更新