React Sidebar组件打开/关闭

时间:2019-02-05 20:37:42

标签: reactjs material-ui

我有多个组成部分,可以组成一个完整的页面。 Main.js加载要加载的三个组件Sidebar,AppBarPanel和Content。现在,我不断收到以下错误。你们有什么主意我该如何解决这个问题?

TypeError: Cannot read property 'classes' of undefined
AppBarPanel.render
C:/Users/***/source/AnVsRe/PermissionAdmin/src/components/Include/AppBarPanel.js:56
  53 | });
  54 | 
  55 | class AppBarPanel extends Component {
> 56 | render({ classes, open, handleDrawerOpen }) {
  57 |     return (
  58 |       <Fragment>
  59 |         <AppBar

Main.js .......

const drawerWidth = 240;

const styles = theme => ({
  content: {
    flexGrow: 1,
    padding: theme.spacing.unit * 3,
    transition: theme.transitions.create('margin', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
    marginLeft: -drawerWidth,
  },
  contentShift: {
    transition: theme.transitions.create('margin', {
      easing: theme.transitions.easing.easeOut,
      duration: theme.transitions.duration.enteringScreen,
    }),
    marginLeft: "10px",
  },
});

class main extends Component { 
  state = {
    open: true,
  }; 

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

  handleDrawerOpen = () => {
    this.setState({ open: true });
  };

  handleDrawerClose = () => {
    this.setState({ open: false });
  };

  render () { 
    const { classes } = this.props;
    const { open } = this.state;

    return (
        <Fragment>
          <CssBaseline />
          <AppBarPanel 
            handleDrawerOpen={this.handleDrawerOpen}
            open={open}
          />
          <Sidebar 
            handleDrawerClose={this.handleDrawerClose}
            drawerHeaderClass={classes.drawerHeader}
            open={open}
          />
          <Content
            drawerHeaderClass={classes.drawerHeader} 
            open={open} 
          />
        </Fragment>
    )
  }
}

Sidebar.js .........

const drawerWidth = 240;

const styles = theme => ({
    hide: {
      display: 'none',
    },
    drawer: {
      width: drawerWidth,
      flexShrink: 0,
    },
    drawerPaper: {
      width: drawerWidth,
    },
    drawerHeader: {
      display: 'flex',
      alignItems: 'center',
      padding: '0 8px',
      ...theme.mixins.toolbar,
      justifyContent: 'flex-end',
    },
  });


  const Sidebar = ({
    classes,
    drawerHeaderClass,
    theme,
    handleDrawerClose,
    open
  }) => {
    return (
            <Fragment>
            <Drawer className={classes.drawer}
                    variant="persistent"
                    anchor="left"
                    open={open}
                    classes={{
                        paper: classes.drawerPaper,
                    }}
            >
              <div className={classes.drawerHeader}>
              <img src={ADMLogo} style={{height:'40px',marginRight:'100px'}} alt="ADM Logo" />
              </div>
              <div className={drawerHeaderClass}>
                <IconButton onClick={handleDrawerClose}>
                  {theme.direction === "ltr" ? (
                    <ChevronLeftIcon />
                  ) : (
                    <ChevronRightIcon />
                  )}
                </IconButton>
              </div>
              <Divider />
              <List>
                <ListItem>
                  <Avatar alt="John Walls" src={AvatarImg} />
                    <span style={{whiteSpace: 'nowrap', fontVariant: 'small-caps', marginLeft: '10px'}}>John Walls</span>
                  </ListItem>
              </List>
              <Divider />
              <List>
                <ListItem button component="a" href="/">
                    <SettingsIcon />
                    <ListItemText primary="User's Permissions" />
                  </ListItem>
                <ListItem button component="a" href="/groups">
                    <SettingsIcon />
                    <ListItemText primary="Groups" />
                  </ListItem>
                <ListItem button component="a" href="/permissions">
                    <SettingsIcon />
                    <ListItemText primary="Permissions" />
                  </ListItem>
              </List>
            </Drawer>
        </Fragment>
        )
    }

AppBarPanel ...........

const drawerWidth = 240;

const styles = theme => ({
  root: {
    display: 'flex',
  },
  appBar: {
    transition: theme.transitions.create(['margin', 'width'], {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
  },
  appBarShift: {
    width: `calc(100% - ${drawerWidth}px)`,
    marginLeft: drawerWidth,
    transition: theme.transitions.create(['margin', 'width'], {
      easing: theme.transitions.easing.easeOut,
      duration: theme.transitions.duration.enteringScreen,
    }),
  },
  menuButton: {
    marginLeft: 12,
    marginRight: 20,
  },
  hide: {
    display: 'none',
  },
  content: {
    flexGrow: 1,
    padding: theme.spacing.unit * 3,
    transition: theme.transitions.create('margin', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
    marginLeft: -drawerWidth,
  },
  contentShift: {
    transition: theme.transitions.create('margin', {
      easing: theme.transitions.easing.easeOut,
      duration: theme.transitions.duration.enteringScreen,
    }),
    marginLeft: "10px",
  },
});

class AppBarPanel extends Component {
render({ classes, open, handleDrawerOpen }) {
    return (
      <Fragment>
        <AppBar
          style={{ color:"#000000", background: '#FFF', boxShadow: 'none',borderBottom:'1px solid #CCC'}}
          position="fixed"
          className={classNames(classes.appBar, {
            [classes.appBarShift]: open,
          })}
        >
          <Toolbar disableGutters={!open}>
            <IconButton
              color="inherit"
              aria-label="Open drawer"
              onClick={handleDrawerOpen}
              className={classNames(classes.menuButton, open && classes.hide)}
            >
              <MenuIcon />
            </IconButton>
            <Typography variant="h6" color="inherit" noWrap>
              User Permissions
            </Typography>
          </Toolbar>
        </AppBar>
      </Fragment>
    )
  }
}

content.js

const drawerWidth = 240;
const styles = theme => ({
    content: {
      flexGrow: 1,
      padding: theme.spacing.unit * 3,
      transition: theme.transitions.create("margin", {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.leavingScreen
      }),
      marginLeft: -drawerWidth
    },
    contentShift: {
      transition: theme.transitions.create("margin", {
        easing: theme.transitions.easing.easeOut,
        duration: theme.transitions.duration.enteringScreen
      }),
      marginLeft: 0
    }
  });

const content = ({ classes, open, drawerHeaderClass, match }) => {
    return (
        <main
            className={classNames(classes.content, {
            [classes.contentShift]: open,
        })}>
                <Grid container style={{margin: '50px 0 0 230px', minWidth:'600px'}}>
                <Grid item md={8}>
                    <Router page={match.params.type} />
                </Grid>
                </Grid>
        </main> 
    );
}

1 个答案:

答案 0 :(得分:4)

AppBarPanel的render方法不带参数。 See docs

更改以下行:

render({ classes, open, handleDrawerOpen }) {
    return (
    ...

收件人:

render() {
    const { classes, open, handleDrawerOpen } = this.props;
    return (
    ...

此外,我看到您在声明样式,但未导出用withStyles包装的组件。您应该在每个文件中执行此操作:

export default withStyles(styles)(YourComponent);

请参见withStyles docsan example