我有一个更大的组件,具有多个状态和道具。此组件负责页眉和侧边栏。 (将菜单移到左侧)。所以我想将其拆分为两个文件,但是做得不好。
此组件具有const Drawer,这正是我想要移动到另一个文件(以及状态和所有样式)的内容 这是我的一个更大的组件:
import React, { Component } from 'react';
import { withStyles } from '@material-ui/core/styles';
import classNames from 'classnames';
import Drawer from '@material-ui/core/Drawer';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import ListItem from '@material-ui/core/ListItem';
import List from '@material-ui/core/List';
// import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
const drawerWidth = 240;
const styles = theme => ({
root: {
flexGrow: 1
},
appFrame: {
height: 430,
zIndex: 1,
overflow: 'hidden',
position: 'relative',
display: 'flex',
width: '100%'
},
appBar: {
position: 'absolute',
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
})
},
'appBarShift-left': {
marginLeft: drawerWidth
},
'appBarShift-right': {
marginRight: drawerWidth
},
menuButton: {
marginLeft: 12,
marginRight: 20
},
hide: {
display: 'none'
},
drawerPaper: {
position: 'relative',
width: drawerWidth
},
drawerHeader: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: '0 8px',
...theme.mixins.toolbar
},
content: {
flexGrow: 1,
backgroundColor: theme.palette.background.default,
padding: theme.spacing.unit * 3,
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
'content-left': {
marginLeft: -drawerWidth
},
'content-right': {
marginRight: -drawerWidth
},
contentShift: {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
})
},
'contentShift-left': {
marginLeft: 0
},
'contentShift-right': {
marginRight: 0
}
});
export default withStyles(styles, { withTheme: true })(
class Header extends Component {
state = {
open: true,
anchor: 'left'
};
handleDrawerToggle = () => {
const open = this.state.open;
this.setState({
open: !open
});
};
render() {
const { classes, theme } = this.props;
const { anchor, open } = this.state;
const drawer = (
<Drawer
variant="persistent"
anchor={anchor}
open={open}
classes={{
paper: classes.drawerPaper
}}
>
<div className={classes.drawerHeader} />
<Divider />
<List component="nav">
<ListItem button>
<ListItemText primary="One ListItem" />
</ListItem>
<ListItem button>
<ListItemText primary="Two ListItem" />
</ListItem>
</List>
</Drawer>
);
return (
<div className={classes.appFrame}>
<AppBar
className={classNames(classes.appBar, {
[classes.appBarShift]: open,
[classes[`appBarShift-${anchor}`]]: open
})}
>
<Toolbar disableGutters={!open}>
<IconButton
color="inherit"
aria-label="Open drawer"
onClick={this.handleDrawerToggle}
className={classNames(classes.menuButton)}
>
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit" noWrap>
Example Text
</Typography>
</Toolbar>
</AppBar>
{drawer}
<main
className={classNames(classes.content, classes[`content-${anchor}`], {
[classes.contentShift]: open,
[classes[`contentShift-${anchor}`]]: open
})}
>
<div className={classes.drawerHeader} />
<Typography>You think water moves fast? You should see ice.</Typography>
</main>
</div>
);
}
}
);
这是我尝试将其拆分为两个文件,但不起作用。 它编译成功,但是显示不正确。
Header.js :
import React, { Component } from 'react';
import { withStyles } from '@material-ui/core/styles';
import classNames from 'classnames';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import Sidebar from './Sidebar';
const drawerWidth = 240;
const styles = theme => ({
root: {
flexGrow: 1
},
appFrame: {
height: 430,
zIndex: 1,
overflow: 'hidden',
position: 'relative',
display: 'flex',
width: '100%'
},
appBar: {
position: 'absolute',
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
})
},
'appBarShift-left': {
marginLeft: drawerWidth
},
'appBarShift-right': {
marginRight: drawerWidth
},
menuButton: {
marginLeft: 12,
marginRight: 20
},
hide: {
display: 'none'
},
drawerPaper: {
position: 'relative',
width: drawerWidth
},
drawerHeader: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: '0 8px',
...theme.mixins.toolbar
},
content: {
flexGrow: 1,
backgroundColor: theme.palette.background.default,
padding: theme.spacing.unit * 3,
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
'content-left': {
marginLeft: -drawerWidth
},
'content-right': {
marginRight: -drawerWidth
},
contentShift: {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
})
},
'contentShift-left': {
marginLeft: 0
},
'contentShift-right': {
marginRight: 0
}
});
export default withStyles(styles, { withTheme: true })(
class Header extends Component {
state = {};
handleDrawerToggle = () => {
const open = this.props.open;
this.setState({
open: !open
});
};
render() {
const { classes, theme } = this.props;
const { anchor, open } = this.props;
return (
<div className={classes.appFrame}>
<AppBar
className={classNames(classes.appBar, {
[classes.appBarShift]: open,
[classes[`appBarShift-${anchor}`]]: open
})}
>
<Toolbar disableGutters={!open}>
<IconButton
color="inherit"
aria-label="Open drawer"
onClick={this.handleDrawerToggle}
className={classNames(classes.menuButton)}
>
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit" noWrap>
Example Text
</Typography>
</Toolbar>
</AppBar>
<Sidebar />
<main
className={classNames(classes.content, classes[`content-${anchor}`], {
[classes.contentShift]: open,
[classes[`contentShift-${anchor}`]]: open
})}
>
<div className={classes.drawerHeader} />
<Typography>You think water moves fast? You should see ice.</Typography>
</main>
</div>
);
}
}
);
Sidebar.js:
import React, { Component } from 'react';
import ListItem from '@material-ui/core/ListItem';
import List from '@material-ui/core/List';
import { withStyles } from '@material-ui/core/styles';
// import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import Divider from '@material-ui/core/Divider';
const drawerWidth = 240;
const styles = theme => ({
drawerPaper: {
position: 'relative',
width: drawerWidth
},
drawerHeader: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: '0 8px',
...theme.mixins.toolbar
}
});
export default withStyles(styles, { withTheme: true })(
class Sidebar extends Component {
state = {
open: true,
anchor: 'left'
};
render() {
const { classes, theme } = this.props;
const { anchor, open } = this.state;
return (
<Drawer
variant="persistent"
anchor={anchor}
open={open}
classes={{
paper: classes.drawerPaper
}}
>
<div className={classes.drawerHeader} />
<Divider />
<List component="nav">
<ListItem button>
<ListItemText primary="One ListItem" />
</ListItem>
<ListItem button>
<ListItemText primary="Two ListItem" />
</ListItem>
</List>
</Drawer>
);
}
}
);
答案 0 :(得分:0)
您正在标题组件中设置状态open
,但没有将其传递给Sidebar
组件作为控制它的道具。
答案 1 :(得分:0)
我假设您选择Header Component来管理open
状态属性,这样:
您的标头组件应处于打开状态,并且具有切换功能。
class Header extends Component {
state = {
open: true,
};
handleDrawerToggle = () => {
const open = this.state.open;
this.setState({
open: !open
});
};
render() { ...
<Sidebar open={this.state.open} anchor="left" />
}
}
和侧边栏组件应该从道具中接收其他物品
const Sidebar = () => {
const { classes, theme, anchor, open } = this.props;
return (
...
)
};
答案 2 :(得分:0)
您没有传递道具,这可能是问题所在。但是类似的事情应该起作用。
实现此目标的最佳方法是使用无状态组件,并传递您需要呈现的数据。
您可以这样编写主要组件:
import React, { Component } from 'react';
import { withStyles } from '@material-ui/core/styles';
import classNames from 'classnames';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import Sidebar from './Sidebar';
const drawerWidth = 240;
const styles = theme => ({
root: {
flexGrow: 1
},
appFrame: {
height: 430,
zIndex: 1,
overflow: 'hidden',
position: 'relative',
display: 'flex',
width: '100%'
},
appBar: {
position: 'absolute',
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
})
},
'appBarShift-left': {
marginLeft: drawerWidth
},
'appBarShift-right': {
marginRight: drawerWidth
},
menuButton: {
marginLeft: 12,
marginRight: 20
},
hide: {
display: 'none'
},
drawerPaper: {
position: 'relative',
width: drawerWidth
},
drawerHeader: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: '0 8px',
...theme.mixins.toolbar
},
content: {
flexGrow: 1,
backgroundColor: theme.palette.background.default,
padding: theme.spacing.unit * 3,
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
'content-left': {
marginLeft: -drawerWidth
},
'content-right': {
marginRight: -drawerWidth
},
contentShift: {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
})
},
'contentShift-left': {
marginLeft: 0
},
'contentShift-right': {
marginRight: 0
}
});
export default withStyles(styles, { withTheme: true })(
class Header extends Component {
state = {
open: true,
anchor: 'left'
};
handleDrawerToggle = () => {
const open = this.state.open;
this.setState({
open: !open
});
};
render() {
const { classes, theme } = this.props;
const { anchor, open } = this.state;
return (
<div className={classes.appFrame}>
<AppBar
className={classNames(classes.appBar, {
[classes.appBarShift]: open,
[classes[`appBarShift-${anchor}`]]: open
})}
>
<Toolbar disableGutters={!open}>
<IconButton
color="inherit"
aria-label="Open drawer"
onClick={this.handleDrawerToggle}
className={classNames(classes.menuButton)}
>
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit" noWrap>
Example Text
</Typography>
</Toolbar>
</AppBar>
<Sidebar anchor={anchor} open={open} classes={classes} />
<main
className={classNames(classes.content, classes[`content-${anchor}`], {
[classes.contentShift]: open,
[classes[`contentShift-${anchor}`]]: open
})}
>
<div className={classes.drawerHeader} />
<Typography>You think water moves fast? You should see ice.</Typography>
</main>
</div>
);
}
}
);
和Sidebar
组件类似:
import Drawer from '@material-ui/core/Drawer';
import ListItem from '@material-ui/core/ListItem';
import List from '@material-ui/core/List';
import ListItemText from '@material-ui/core/ListItemText';
const Sidebar = ({ anchor, open, classes }) => (
<Drawer
variant="persistent"
anchor={anchor}
open={open}
classes={{
paper: classes.drawerPaper
}}
>
<div className={classes.drawerHeader} />
<Divider />
<List component="nav">
<ListItem button>
<ListItemText primary="One ListItem" />
</ListItem>
<ListItem button>
<ListItemText primary="Two ListItem" />
</ListItem>
</List>
</Drawer>
);