css - 是否可以将函数传递到组件内的 Material-UI withStyles() 中

标签 css reactjs material-ui next.js

我正在尝试将仪表板的组件拆分为更小的组件。然而,所有组件都取决于抽屉宽度。我的第一个想法是将抽屉宽度移动到状态中,这样我就可以将它传递到每个组件中。但是,可变样式取决于抽屉宽度。在研究material-ui文档和引用元素时,样式总是在类之外。

我尝试在类中移动这两个变量,并通过类的引用将函数传递到 withStyle 中,但这也失败了。页面的 css 已关闭,我收到一条警告,说我向 withStyles 传递了无效函数。如下所示。

export default withStyles(DashboardLayout.styles)(DashboardLayout);

distorted css image 这是代码最初的样子。

import PropTypes from 'prop-types';
import classNames from 'classnames';
import { withStyles } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import Drawer from '@material-ui/core/Drawer';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import List from '@material-ui/core/List';
import Typography from '@material-ui/core/Typography';
import Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import Badge from '@material-ui/core/Badge';
import MenuIcon from '@material-ui/icons/Menu';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import NotificationsIcon from '@material-ui/icons/Notifications';
import { mainListItems, secondaryListItems } from './listItems';

const drawerWidth = 240;

const styles = theme => ({
  root: {
    display: 'flex',
  },
  toolbar: {
    paddingRight: 24, // keep right padding when drawer closed
  },
  toolbarIcon: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: '0 8px',
    ...theme.mixins.toolbar,
  },
  appBar: {
    zIndex: theme.zIndex.drawer + 1,
    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: {
    marginLeft: 12,
    marginRight: 36,
  },
  menuButtonHidden: {
    display: 'none',
  },
  title: {
    flexGrow: 1,
  },
  drawerPaper: {
    position: 'relative',
    whiteSpace: 'nowrap',
    width: drawerWidth,
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen,
    }),
  },
  drawerPaperClose: {
    overflowX: 'hidden',
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
    width: theme.spacing.unit * 7,
    [theme.breakpoints.up('sm')]: {
      width: theme.spacing.unit * 9,
    },
  },
  appBarSpacer: theme.mixins.toolbar,
  content: {
    flexGrow: 1,
    padding: theme.spacing.unit * 3,
    height: '100vh',
    overflow: 'auto',
  },
  chartContainer: {
    marginLeft: -22,
  },
  tableContainer: {
    height: 320,
  },
  h5: {
    marginBottom: theme.spacing.unit * 2,
  },
});

class DashboardLayout extends React.Component {
  state = {
    open: true,
  };

  handleDrawerToggle = () => {
    this.setState({ open: !this.state.open });
  };

  render() {
    const { classes, children } = this.props;

    return (
      <div className={classes.root}>
        <CssBaseline />
        <AppBar
          position="absolute"
          className={classNames(classes.appBar, this.state.open && classes.appBarShift)}
        >
          <Toolbar disableGutters={!this.state.open} className={classes.toolbar}>
            <IconButton
              color="inherit"
              aria-label="Open drawer"
              onClick={this.handleDrawerToggle}
              className={classNames(
                classes.menuButton,
                this.state.open && classes.menuButtonHidden,
              )}
            >
              <MenuIcon />
            </IconButton>
            <Typography
              component="h1"
              variant="h6"
              color="inherit"
              noWrap
              className={classes.title}
            >
              Dashboard
            </Typography>
            <IconButton color="inherit">
              <Badge badgeContent={4} color="secondary">
                <NotificationsIcon />
              </Badge>
            </IconButton>
          </Toolbar>
        </AppBar>
        <Drawer
          variant="permanent"
          classes={{
            paper: classNames(classes.drawerPaper, !this.state.open && classes.drawerPaperClose),
          }}
          open={this.state.open}
        >
          <div className={classes.toolbarIcon}>
            <IconButton onClick={this.handleDrawerToggle}>
              <ChevronLeftIcon />
            </IconButton>
          </div>
          <Divider />
          <List>{mainListItems}</List>
          <Divider />
        </Drawer>
        <main className={classes.content}>
          { this.props.children }
          <div> Children </div>
        </main>
      </div>
    );
  }
}

DashboardLayout.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(DashboardLayout);

The image of what my code is supposed to look like

我想将抽屉、应用栏移动到它们自己的文件中,而不必在每个文件中对抽屉宽度和样式进行硬编码。

最佳答案

您可以将drawerWidth放入自定义主题中,以便较小的组件可以从theme.drawerWidth访问它。官方组件将使用theme's values against some specific keys (即 palette),但您始终可以为自己的组件添加更多键。 Docs on themes

例如,使用 createMuiTheme 创建主题并将其作为 prop 传递给 MuiThemeProvider:

const theme = createMuiTheme({
  drawerWidth: 200 // a custom key in theme object
});

function Root() {
  return (
    <MuiThemeProvider theme={theme}>
      <App/>
    </MuiThemeProvider>
  );
}

现在,您可以使用 withStyles 从较小组件中的 theme 访问 drawerWidth,例如:

// your appbar's own style
const styles = theme => ({ 
  appBar: {
    width: `calc(100% - ${theme.drawerWidth}px)`,
    marginLeft: theme.drawerWidth
  }
})
export default withStyles(styles)(YourAppBar);

// your drawer's own style
const styles = theme => ({  
  drawer: {
    width: theme.drawerWidth,
    flexShrink: 0
  },
  drawerPaper: {
    width: theme.drawerWidth
  }
})
export default withStyles(styles)(YourDrawer);

这是沙箱中的示例:https://codesandbox.io/s/7j4y8p6nox

关于css - 是否可以将函数传递到组件内的 Material-UI withStyles() 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54833185/

相关文章:

html - "overwrite" Bootstrap 颜色的正确方法是什么? (以及可选的其他 CSS 选择器)

jquery - 滚动时降低div的高度

reactjs - 部署到 Github 页面时未加载图像

reactjs - 如何为所有 Material-UI 组件添加填充和边距?

reactjs - 如何将 Material UI v5 连接到 Next JS v12?

html - 具有方形比例和 flexbox 的内部 div

javascript - -webkit translate3d 大元素断断续续

javascript - 操纵 JSX 元素的子集合

javascript - 如何使用 ReactJs 设计像电子商务网站那样的通用过滤器?

reactjs - 在 React Material-UI DataGrid 中获取复选框选择上的行项目