如何重构共享主题信息的材质 UI 演示



我正在查看使用以下示例代码作为小应用程序周围的框架:

https://material-ui.com/components/drawers/#MiniDrawer.js

在尝试将元素重构为单独的组件时,我遇到了一个问题。将代码剪切并粘贴到全新的create-react-app应用程序中工作正常。但是,一旦我尝试将 AppBar 和抽屉重构为单独的组件,我怀疑它们会相互跟踪。

我在 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% - ${drawerWidth}px)`,
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;

。并将应用栏和抽屉放入自己的文件中:

// 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.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 上下文来执行此操作?坦率地说,我被难住了。:-(

主要问题是导入useStyles的位置。它需要排在最后,以确保它定义的样式放在<head>中的默认样式之后。有关原因的详细信息,请参阅此相关答案:从单个文件导出的材质 UI v4 makeStyles 在刷新时不会保留样式。

以下是沙盒的固定版本:https://codesandbox.io/s/fixed-usestyles-import-q0m8z。

我所做的只是将useStyles导入App.js

相关内容

  • 没有找到相关文章

最新更新