如何重构分享主题信息的material-ui demo
Posted
技术标签:
【中文标题】如何重构分享主题信息的material-ui demo【英文标题】:How to refactor material-ui demo that shares theme information 【发布时间】:2020-02-11 05:39:32 【问题描述】:我正在查看使用以下示例代码围绕一个小应用程序的框架:
https://material-ui.com/components/drawers/#MiniDrawer.js
在尝试将元素重构为单独的组件时,我遇到了一个问题。将代码剪切并粘贴到全新的create-react-app
应用程序中可以正常工作。但是,当我尝试将 AppBar 和 Drawer 重构为单独的组件时,我怀疑它们会失去对彼此的跟踪。
My version 在 codesandbox.io 上。
我首先将useStyles
提取到一个单独的文件中:
// useStyles.js
import makeStyles from '@material-ui/core/styles';
const drawerWidth = 240;
const useStyles = makeStyles(theme => (
root:
display: 'flex',
,
appBar:
zIndex: theme.zIndex.drawer + 100,
transition: theme.transitions.create(['width', 'margin'],
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
),
,
appBarShift:
marginLeft: drawerWidth,
width: `calc(100% - $drawerWidthpx)`,
transition: theme.transitions.create(['width', 'margin'],
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
),
,
menuButton:
marginRight: 36,
,
hide:
display: 'none',
,
drawer:
width: drawerWidth,
flexShrink: 0,
whiteSpace: 'nowrap',
,
drawerOpen:
width: drawerWidth,
transition: theme.transitions.create('width',
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
),
,
drawerClose:
transition: theme.transitions.create('width',
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
),
overflowX: 'hidden',
width: theme.spacing(7) + 1,
[theme.breakpoints.up('sm')]:
width: theme.spacing(9) + 1,
,
,
toolbar:
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
...theme.mixins.toolbar,
,
content:
flexGrow: 1,
padding: theme.spacing(3),
,
));
export default useStyles;
... 并将 AppBar 和 Drawers 放入自己的文件中:
// MyUIAppBar.js
import React from 'react';
import clsx from 'clsx';
// ...
import Mail, Notifications, Menu from '@material-ui/icons';
function MyUIAppBar(props)
const classes = props.classes;
const toggleDrawer = props.toggleDrawer;
const open = props.open;
return(
<AppBar
position="fixed"
className=clsx(classes.appBar,
[classes.appBarShift]: open,
)
>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick=toggleDrawer
edge="start"
className=clsx(classes.menuButton,
[classes.hide]: open,
)
>
<Menu />
</IconButton>
<Typography component="h1" variant="h6" color="inherit" noWrap className=classes.title>
MDS MyUI
</Typography>
// ...
</Toolbar>
</AppBar>
);
export default MyUIAppBar;
和
// MyUIDrawer.js
import React from 'react';
import clsx from 'clsx';
import Drawer from '@material-ui/core/Drawer';
import IconButton from '@material-ui/core/IconButton';
import ChevronLeft, ChevronRight from '@material-ui/icons';
function MyUIDrawer(props)
const classes = props.classes;
const toggleDrawer = props.toggleDrawer;
const open = props.open;
return (
<Drawer
variant="permanent"
className=clsx(classes.drawer,
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
)
classes=
paper: clsx(
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
),
open=open
onToggle=toggleDrawer
>
<div className=classes.toolbar>
<IconButton onClick=toggleDrawer>
open ? <ChevronRight /> : <ChevronLeft />
</IconButton>
</div>
props.children
</Drawer>
);
export default MyUIDrawer;
在主 App 文件中,我必须将主题、打开、类和 toggleDrawer 作为道具传递给两个组件:
// App.js
import React from 'react';
import useStyles from './styles';
import WebUIDrawer from './components/WebUIDrawer';
import WebUIAppBar from './components/WebUIAppBar';
import useToggle from './hooks';
import useTheme from '@material-ui/core/styles';
// ... various imports here
export default function App()
const classes = useStyles();
const theme = useTheme();
const [ open, toggleDrawer ] = useToggle(true);
return (
<div className=classes.root>
<CssBaseline />
<WebUIAppBar theme=theme open=open classes=classes toggleDrawer=toggleDrawer/>
<WebUIDrawer open=open classes=classes toggleDrawer=toggleDrawer >
<List>
['Eeny', 'Meeny', 'Miney', 'Mo'].map((text, index) => (
<ListItem button key=text>
<ListItemIcon>index % 2 === 0 ? <MoveToInbox /> : <Mail /></ListItemIcon>
<ListItemText primary=text />
</ListItem>
))
</List>
</WebUIDrawer>
<Main classes=classes/>
</div>
);
结果排序可行,但菜单的分层和偏移似乎存在问题。我怀疑主题在两者之间没有更新。有没有更好的方法在组件之间共享样式信息?是否可以使用 React 上下文来执行此操作?坦率地说,我很难过。 :-(
【问题讨论】:
如果您可以包含一个重现您的问题的CodeSandbox,将会很有帮助。 你的愿望就是我的命令 ;-) 希望这能让问题更清楚...codesandbox.io/s/thirsty-mestorf-y46x7 【参考方案1】:主要问题是useStyles
的导入位置。它需要放在最后,以确保将其定义的样式置于<head>
中的默认样式之后。有关原因的详细信息,请参阅此相关答案:Material UI v4 makeStyles exported from a single file doesn't retain the styles on refresh。
这是您的沙盒的固定版本:https://codesandbox.io/s/fixed-usestyles-import-q0m8z。
我所做的只是将useStyles
导入移动到App.js
。
【讨论】:
是的,...但我怀疑您使用的是工程师的锤子... 10 秒敲击它,2 年知道敲击它的位置。谢谢瑞恩,你是一个理智的保护者:-)以上是关于如何重构分享主题信息的material-ui demo的主要内容,如果未能解决你的问题,请参考以下文章
如何在 material-ui 主题中导入和使用自定义字体?
如何更改 Material-UI AppBar 的明暗主题颜色?