React.js - 了解钩子及其规则
React.js - understanding hooks and their rules
我是学习 React 的新手,我正在尝试理解 hooks,但一直对 Hooks 的规则感到困惑。
我有一个正在构建的应用程序,它在左侧下方有一个导航栏,其图标在单击时会打开模式:
我现在正在尝试设置 'modal wrapper' 以包含使用 this codesandbox as an example (from 堆栈溢出答案的每个模态框),但是我 运行 遇到规则问题钩子和脱钩。
我一直在阅读文档 here 中有关 reach hooks 的内容,并了解仅在顶层和函数中调用 hooks 的理论,但由于我的代码中有很多 hooks,我我对应该在哪里调用哪些挂钩以及如何调用感到困惑 link 返回给它们。
我也对 classes
与 functions
的用法感到有点困惑,因为我试图遵循的示例使我们成为 class 并且我是习惯使用函数编码。
我当前的代码如下:
import React, { Component } from 'react'
import { Router, Link } from "react-router-dom";
import Modal from "react-modal";
import { createBrowserHistory } from 'history'
import { useAuth0 } from "@auth0/auth0-react";
import LogoutButton from "../Logout-Button";
import LoginButton from "../Login-Button";
import { Nav } from "react-bootstrap";
import Auth0ProviderWithHistory from '../../auth0-provider-with-history'
import UserSettings from "./UserSettings";
import Dashboard from "./Dashboard/Dashboard";
import MEMsLine from "./MemsLine";
import MEMsGrid from "./MemsGrid";
import Copyright from "../Copyright";
import clsx from 'clsx'
import { makeStyles } from '@material-ui/core/styles'
import {
CssBaseline,
Drawer,
Box,
AppBar,
Toolbar,
List,
Divider,
IconButton,
Container,
ListItem,
ListItemText,
ListItemIcon,
} from '@material-ui/core'
import {
ArrowBackIos as ArrowBackIcon,
Menu as MenuIcon,
Dashboard as DashboardIcon,
History as MEMsIcon,
People as PeopleIcon,
Place as PlaceIcon,
Cake as EventIcon,
LibraryMusic as MusicIcon,
Tv as TVIcon,
LocalMovies as MovieIcon,
SportsEsports as GameIcon,
Timeline as MEMslineIcon,
Settings as SettingsIcon,
} from '@material-ui/icons'
const history = createBrowserHistory();
const drawerWidth = 200
const useStyles = makeStyles((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: {
marginRight: 36,
},
menuButtonHidden: {
display: 'none',
},
title: {
flexGrow: 1,
},
drawerPaper: {
position: 'relative',
whiteSpace: 'nowrap',
backgroundColor: 'black',
color: 'white',
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,
}),
paddingLeft: '8px',
width: theme.spacing(7),
[theme.breakpoints.up('sm')]: {
width: theme.spacing(9),
},
},
appBarSpacer: theme.mixins.toolbar,
content: {
flexGrow: 1,
height: '100vh',
overflow: 'auto',
},
container: {
paddingTop: theme.spacing(4),
paddingBottom: theme.spacing(4),
},
paper: {
padding: theme.spacing(2),
display: 'flex',
overflow: 'auto',
flexDirection: 'column',
},
fixedHeight: {
height: 240,
},
navLink: {
textDecoration: 'none',
color: 'inherit',
},
appBarImage: {
maxHeight: '75px',
marginLeft: '-40px',
paddingRight: '20px',
},
personIcon: {
background: '#000000',
display: 'flex',
flexDirection: 'row',
},
}))
class UserAccount extends Component {
state = {
loginOpened: false,
signupOpened: false
};
openModal = modalType => () => {
if (modalType === "login") {
this.setState({
loginOpened: true,
signupOpened: false
});
} else if (modalType === "signup") {
this.setState({
loginOpened: false,
signupOpened: true
});
}
};
closeModal = modalType => () => {
if (modalType === "login") {
this.setState({
loginOpened: false
});
} else if (modalType === "signup") {
this.setState({
signupOpened: false
});
}
};
render() {
const { loginOpened, signupOpened } = this.state;
const classes = useStyles()
const [open, setOpen] = React.useState(false)
const handleDrawerOpen = () => {
setOpen(true)
}
const handleDrawerClose = () => {
setOpen(false)
}
const AuthNav = () => {
const { isAuthenticated } = useAuth0();
return (
<Nav className="justify-content-end">
{isAuthenticated ? <LogoutButton /> : <LoginButton />}
</Nav>
);
};
return (
// <AuthConsumer>
// {({ user }) => (
// <Can
// role={user.role}
// perform="useraccount:visit"
// yes={() => (
<Router history={history}>
<Auth0ProviderWithHistory>
<div className={classes.root}>
<CssBaseline />
<AppBar style={{ background: '#000000' }}
position="absolute"
className={clsx(classes.appBar, open && classes.appBarShift)}
>
<Toolbar className={classes.toolbar}>
<IconButton
edge="start"
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
className={clsx(
classes.menuButton,
open && classes.menuButtonHidden
)}
>
<MenuIcon />
</IconButton>
<Link to="/" className={classes.navLink}>
<img
className={classes.appBarImage}
src='https://storage.googleapis.com/mems-images/mems-logo-small-rounded.png'
alt="mems logo"
/>
</Link>
<div className={classes.personIcon} style={{ width: '100%', justifyContent: 'flex-end' }}>
<AuthNav />
</div>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
classes={{
paper: clsx(classes.drawerPaper, !open && classes.drawerPaperClose),
}}
open={open}
>
<div className={classes.toolbarIcon}>
<IconButton onClick={handleDrawerClose}>
<ArrowBackIcon style={{ color: 'white' }} />
</IconButton>
</div>
<Divider />
<List>
<ListItem button>
<ListItemIcon>
<SettingsIcon style={{ color: 'white' }} />
<UserSettings />
</ListItemIcon>
<ListItemText primary="Settings" />
</ListItem>
<ListItem button>
<ListItemIcon>
<DashboardIcon style={{ color: 'white' }} />
<Dashboard />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
<ListItem button>
<ListItemIcon>
<MEMslineIcon style={{ color: 'white' }} />
<MEMsLine />
</ListItemIcon>
<ListItemText primary="MEMsLine" />
</ListItem>
<ListItem button>
<ListItemIcon>
<MEMsIcon style={{ color: 'white' }} />
<MEMsGrid />
</ListItemIcon>
<ListItemText primary="All MEMs" />
</ListItem>
<ListItem button>
<ListItemIcon>
<EventIcon style={{ color: 'white' }} />
<p>Events</p>
</ListItemIcon>
<ListItemText primary="Events" />
</ListItem>
<ListItem button>
<ListItemIcon>
<PeopleIcon style={{ color: 'white' }} />
<p>People</p>
</ListItemIcon>
<ListItemText primary="People" />
</ListItem>
<ListItem button>
<ListItemIcon>
<PlaceIcon style={{ color: 'white' }} />
<p>Places</p>
</ListItemIcon>
<ListItemText primary="Places" />
</ListItem>
<ListItem button>
<ListItemIcon>
<MusicIcon style={{ color: 'white' }} />
<p>Music</p>
</ListItemIcon>
<ListItemText primary="Music" />
</ListItem>
<ListItem button>
<ListItemIcon>
<MovieIcon style={{ color: 'white' }} />
<p>Movies</p>
</ListItemIcon>
<ListItemText primary="Movies" />
</ListItem>
<ListItem button>
<ListItemIcon>
<TVIcon style={{ color: 'white' }} />
<p>TV Shows</p>
</ListItemIcon>
<ListItemText primary="TV Shows" />
</ListItem>
<ListItem button>
<ListItemIcon>
<GameIcon style={{ color: 'white' }} />
<p>Games</p>
</ListItemIcon>
<ListItemText primary="Games" />
</ListItem>
</List>
<Divider />
</Drawer>
<main className={classes.content}>
<div className={classes.appBarSpacer} />
<Container maxWidth="lg" className={classes.container}>
<Modal isOpen={loginOpened} onRequestClose={this.closeModal("login")}>
<h1>Login</h1>
<button onClick={this.openModal("signup")}>Open Signup</button>
<button onClick={this.closeModal("login")}>Close this modal</button>
</Modal>
<Modal isOpen={signupOpened} onRequestClose={this.closeModal("signup")}>
<h1>Sign Up</h1>
<button onClick={this.openModal("login")}>Open Login</button>
<button onClick={this.closeModal("signup")}>Close this modal</button>
</Modal>
<button onClick={this.openModal("login")}>Open Login</button>
<button onClick={this.openModal("signup")}>Open Signup</button>
<Box pt={4}>
<Copyright />
</Box>
</Container>
</main>
</div>
</Auth0ProviderWithHistory>
</Router >
// )}
// no={() => <Redirect to="/" />}
// />
// )}
// </AuthConsumer>
);
}
}
export default UserAccount
非常欢迎任何指点!
- 我建议您尝试学习更多关于 React 本身的基础知识 and/or javascript。所以我的建议是多读书,从简单的东西开始,然后转向复杂的东西。
- class 组件应始终具有渲染方法,并将状态保持为 属性,如下例所示。另外,请注意函数切换被写为
toggle = () =>{}
而不是 toggle = () => () =>{}
<- 因为这意味着您要返回一个函数而不是仅仅打开函数 body(learn more about arrow functions)
class ClassComponent extends React.Component {
state = {
show: false
};
toggle = () => {
const { show } = this.state;
this.setState({ show: !show });
};
render() {
const { show } = this.state;
return (
<div>
<span>{show ? "Show Class" : "Hide Class"}</span>
<button onClick={this.toggle}>Click here</button>
</div>
);
}
}
- 一个功能组件,过去无法保持状态,但现在可以通过 React hooks 保持状态,如下例所示。
function FunctionComponent(props) {
const [show, setShow] = React.useState(false);
const toggle = () => setShow(!show);
return (
<div>
<span>{show ? "Show Function" : "Hide Function"}</span>
<button onClick={toggle}>Click here</button>
</div>
);
}
了解了这一点后,现在您可以通过以下方式修复您的代码库:
- 您在 class 组件中的渲染方法包含钩子,这是一个 nono,因为钩子可以并且只能与功能组件一起使用
- 您的 class 函数正在返回函数,而不是仅仅让函数被调用,因此当您执行
this.closeModal("login")
时,您必须像 this.closeModal("login")()
一样再次调用它,然后它会起作用.
总而言之,hooks 只能用在函数组件中,它们提供的功能与 class 组件所具有的相同。您可以设置状态,列出一些生命周期方法等等。由于功能组件过去仅用于渲染,现在可能会执行一些简单的逻辑,因此它们可以像 class 组件一样使用。
Link 带有工作示例的代码沙箱是 here。
通过阅读和理解状态和生命周期以及反应钩子,我设法弄清楚如何让它工作。
首先我将 const 类 = useStyles() 修改为 const { 类 } = this.props。我还简化了代码并删除了 handleDrawerOpen 和 handleDrawerClose。
我的最终代码如下所示:
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { useAuth0 } from "@auth0/auth0-react";
import LogoutButton from "../Logout-Button";
import LoginButton from "../Login-Button";
import { Nav } from "react-bootstrap";
import Modal from "react-modal";
import Auth0ProviderWithHistory from '../../auth0-provider-with-history'
import UserSettings from "./UserSettings";
import Dashboard from "./Dashboard/Dashboard";
import MEMsLine from "./MemsLine";
import MEMsGrid from "./MemsGrid";
import Copyright from "../Copyright";
import { withStyles } from '@material-ui/core/styles'
import {
Box,
List,
Divider,
Container,
ListItem,
ListItemIcon,
} from '@material-ui/core'
import {
Dashboard as DashboardIcon,
History as MEMsIcon,
People as PeopleIcon,
Place as PlaceIcon,
Cake as EventIcon,
LibraryMusic as MusicIcon,
Tv as TVIcon,
LocalMovies as MovieIcon,
SportsEsports as GameIcon,
Timeline as MEMslineIcon,
Settings as SettingsIcon,
} from '@material-ui/icons'
const useStyles = theme => ({
root: {
display: 'flex',
flexDirection: 'column',
},
titleBar: {
display: 'flex',
width: '100%',
alignItems: 'center',
background: '#000000',
position: "absolute",
},
titleBarImage: {
marginLeft: '0px',
marginTop: '7px',
maxHeight: '75px',
paddingRight: '20px',
},
mainContainer: {
display: 'flex',
width: '100%',
flexDirection: 'row',
},
menuBar: {
marginTop: '77px',
position: 'relative',
whiteSpace: 'nowrap',
backgroundColor: 'black',
color: 'white',
width: '60px',
},
content: {
display: 'flex',
flexWrap: 'nowrap',
flexGrow: 5,
marginTop: '90px',
height: '92vh',
padding: '10px',
},
modal: {
display: 'flex',
flexWrap: 'nowrap',
justifyContent: 'center',
alignItems: 'center',
},
container: {
display: 'flex',
flexDirection: 'column',
flexWrap: 'nowrap',
justifyContent: 'flex-end',
height: '91vh',
},
paper: {
padding: theme.spacing(2),
display: 'flex',
overflow: 'auto',
flexDirection: 'column',
},
navLink: {
textDecoration: 'none',
color: 'inherit',
},
personIcon: {
background: '#000000',
display: 'flex',
flexDirection: 'row',
},
})
class UserAccount extends Component {
state = {
dashboardOpened: true,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
};
openModal = modalType => () => {
if (modalType === "dashboard") {
this.setState({
dashboardOpened: true,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "memsline") {
this.setState({
dashboardOpened: false,
memslineOpened: true,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "mems") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: true,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "events") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: true,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "people") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: true,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "places") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: true,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "music") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: true,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "movies") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: true,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "tvshows") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: true,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "games") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: true,
settingsOpened: false
});
} else if (modalType === "settings") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: true
});
}
};
closeModal = modalType => () => {
if (modalType === "dashboard") {
this.setState({
dashboardOpened: false
});
} else if (modalType === "memsline") {
this.setState({
memslineOpened: false
});
} else if (modalType === "mems") {
this.setState({
memslineOpened: false
});
}
else if (modalType === "events") {
this.setState({
memslineOpened: false
});
} else if (modalType === "people") {
this.setState({
memslineOpened: false
});
} else if (modalType === "places") {
this.setState({
memslineOpened: false
});
} else if (modalType === "music") {
this.setState({
memslineOpened: false
});
} else if (modalType === "movies") {
this.setState({
memslineOpened: false
});
} else if (modalType === "tvshows") {
this.setState({
memslineOpened: false
});
} else if (modalType === "games") {
this.setState({
memslineOpened: false
});
} else if (modalType === "settings") {
this.setState({
memslineOpened: false
});
}
};
render() {
const { dashboardOpened, memslineOpened, memsOpened, eventsOpened, peopleOpened, placesOpened, musicOpened, moviesOpened, tvshowsOpened, gamesOpened, settingsOpened } = this.state;
const { classes } = this.props
const AuthNav = () => {
const { isAuthenticated } = useAuth0();
return (
<Nav className="justify-content-end">
{isAuthenticated ? <LogoutButton /> : <LoginButton />}
</Nav>
);
};
const modalStyle = {
overlay: {
position: 'absolute',
top: '95px',
bottom: '70px',
left: '50%',
marginLeft: '35px',
marginRight: 'auto',
transform: 'translate(-50%, -0%)',
backgroundColor: 'rgba(255, 255, 255, 0)',
maxWidth: '1500px',
border: 'none',
},
content: {
position: 'absolute',
top: '0px',
left: '0px',
right: '0px',
bottom: '0px',
background: '#fff',
overflow: 'auto',
WebkitOverflowScrolling: 'touch',
padding: '10px',
maxWidth: '1200px',
border: 'none',
}
};
return (
<>
<Auth0ProviderWithHistory>
<div className={classes.root}>
<div className={classes.titleBar}>
<Link to="/" className={classes.navLink}>
<img
className={classes.titleBarImage}
src='https://storage.googleapis.com/mems-images/mems-logo-small-rounded.png'
alt="mems logo"
/>
</Link>
<div className={classes.personIcon} style={{ width: '100%', justifyContent: 'flex-end' }}>
<AuthNav />
</div>
</div>
<div className={classes.mainContainer}>
<List className={classes.menuBar}>
<ListItem button id="dashboardIcon" style={{ backgroundColor: 'black' }}>
<ListItemIcon>
<DashboardIcon onClick={this.openModal("dashboard")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button id="memslineIcon" style={{ backgroundColor: 'black' }}>
<ListItemIcon>
<MEMslineIcon onClick={this.openModal("memsline")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<MEMsIcon onClick={this.openModal("mems")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<EventIcon onClick={this.openModal("events")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<PeopleIcon onClick={this.openModal("people")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<PlaceIcon onClick={this.openModal("places")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<MusicIcon onClick={this.openModal("music")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<MovieIcon onClick={this.openModal("movies")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<TVIcon onClick={this.openModal("tvshows")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<GameIcon onClick={this.openModal("games")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<SettingsIcon onClick={this.openModal("settings")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
</List>
<Divider />
<div id="content" className={classes.content}>
<div id="modal" className={classes.modal}></div>
<Container maxWidth="lg" className={classes.container}>
<Box pt={4}>
<Copyright />
</Box>
</Container>
</div>
</div>
</div>
<Modal
isOpen={dashboardOpened}
onRequestClose={this.closeModal("dashboard")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"dashboard"}
>
<Dashboard />
</Modal>
<Modal
isOpen={memslineOpened}
onRequestClose={this.closeModal("memsline")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"memsline"}
>
<MEMsLine />
</Modal>
<Modal
isOpen={memsOpened}
onRequestClose={this.closeModal("mems")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"mems"}
>
<MEMsGrid />
</Modal>
<Modal
isOpen={eventsOpened}
onRequestClose={this.closeModal("events")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"events"}
>
<h2>Events</h2>
</Modal>
<Modal
isOpen={peopleOpened}
onRequestClose={this.closeModal("people")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"people"}
>
<h2>People</h2>
</Modal>
<Modal
isOpen={placesOpened}
onRequestClose={this.closeModal("places")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"places"}
>
<h2>Places</h2>
</Modal>
<Modal
isOpen={musicOpened}
onRequestClose={this.closeModal("music")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"music"}
>
<h2>Music</h2>
</Modal>
<Modal
isOpen={moviesOpened}
onRequestClose={this.closeModal("movies")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"movies"}
>
<h2>Movies</h2>
</Modal>
<Modal
isOpen={tvshowsOpened}
onRequestClose={this.closeModal("tvshows")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"tv shows"}
>
<h2>TV Shows</h2>
</Modal>
<Modal
isOpen={gamesOpened}
onRequestClose={this.closeModal("games")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"games"}
>
<h2>Games</h2>
</Modal>
<Modal
isOpen={settingsOpened}
onRequestClose={this.closeModal("settings")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"settings"}
>
<UserSettings />
</Modal>
</Auth0ProviderWithHistory>
</>
)
}
}
export default withStyles(useStyles)(UserAccount)
这是实现我所追求的目标的一种相对简单的方法,我确信使用代码可以更高效,但它正在按我希望的方式工作,并且我在此过程中学到了很多东西方式!
我是学习 React 的新手,我正在尝试理解 hooks,但一直对 Hooks 的规则感到困惑。
我有一个正在构建的应用程序,它在左侧下方有一个导航栏,其图标在单击时会打开模式:
我现在正在尝试设置 'modal wrapper' 以包含使用 this codesandbox as an example (from
我一直在阅读文档 here 中有关 reach hooks 的内容,并了解仅在顶层和函数中调用 hooks 的理论,但由于我的代码中有很多 hooks,我我对应该在哪里调用哪些挂钩以及如何调用感到困惑 link 返回给它们。
我也对 classes
与 functions
的用法感到有点困惑,因为我试图遵循的示例使我们成为 class 并且我是习惯使用函数编码。
我当前的代码如下:
import React, { Component } from 'react'
import { Router, Link } from "react-router-dom";
import Modal from "react-modal";
import { createBrowserHistory } from 'history'
import { useAuth0 } from "@auth0/auth0-react";
import LogoutButton from "../Logout-Button";
import LoginButton from "../Login-Button";
import { Nav } from "react-bootstrap";
import Auth0ProviderWithHistory from '../../auth0-provider-with-history'
import UserSettings from "./UserSettings";
import Dashboard from "./Dashboard/Dashboard";
import MEMsLine from "./MemsLine";
import MEMsGrid from "./MemsGrid";
import Copyright from "../Copyright";
import clsx from 'clsx'
import { makeStyles } from '@material-ui/core/styles'
import {
CssBaseline,
Drawer,
Box,
AppBar,
Toolbar,
List,
Divider,
IconButton,
Container,
ListItem,
ListItemText,
ListItemIcon,
} from '@material-ui/core'
import {
ArrowBackIos as ArrowBackIcon,
Menu as MenuIcon,
Dashboard as DashboardIcon,
History as MEMsIcon,
People as PeopleIcon,
Place as PlaceIcon,
Cake as EventIcon,
LibraryMusic as MusicIcon,
Tv as TVIcon,
LocalMovies as MovieIcon,
SportsEsports as GameIcon,
Timeline as MEMslineIcon,
Settings as SettingsIcon,
} from '@material-ui/icons'
const history = createBrowserHistory();
const drawerWidth = 200
const useStyles = makeStyles((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: {
marginRight: 36,
},
menuButtonHidden: {
display: 'none',
},
title: {
flexGrow: 1,
},
drawerPaper: {
position: 'relative',
whiteSpace: 'nowrap',
backgroundColor: 'black',
color: 'white',
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,
}),
paddingLeft: '8px',
width: theme.spacing(7),
[theme.breakpoints.up('sm')]: {
width: theme.spacing(9),
},
},
appBarSpacer: theme.mixins.toolbar,
content: {
flexGrow: 1,
height: '100vh',
overflow: 'auto',
},
container: {
paddingTop: theme.spacing(4),
paddingBottom: theme.spacing(4),
},
paper: {
padding: theme.spacing(2),
display: 'flex',
overflow: 'auto',
flexDirection: 'column',
},
fixedHeight: {
height: 240,
},
navLink: {
textDecoration: 'none',
color: 'inherit',
},
appBarImage: {
maxHeight: '75px',
marginLeft: '-40px',
paddingRight: '20px',
},
personIcon: {
background: '#000000',
display: 'flex',
flexDirection: 'row',
},
}))
class UserAccount extends Component {
state = {
loginOpened: false,
signupOpened: false
};
openModal = modalType => () => {
if (modalType === "login") {
this.setState({
loginOpened: true,
signupOpened: false
});
} else if (modalType === "signup") {
this.setState({
loginOpened: false,
signupOpened: true
});
}
};
closeModal = modalType => () => {
if (modalType === "login") {
this.setState({
loginOpened: false
});
} else if (modalType === "signup") {
this.setState({
signupOpened: false
});
}
};
render() {
const { loginOpened, signupOpened } = this.state;
const classes = useStyles()
const [open, setOpen] = React.useState(false)
const handleDrawerOpen = () => {
setOpen(true)
}
const handleDrawerClose = () => {
setOpen(false)
}
const AuthNav = () => {
const { isAuthenticated } = useAuth0();
return (
<Nav className="justify-content-end">
{isAuthenticated ? <LogoutButton /> : <LoginButton />}
</Nav>
);
};
return (
// <AuthConsumer>
// {({ user }) => (
// <Can
// role={user.role}
// perform="useraccount:visit"
// yes={() => (
<Router history={history}>
<Auth0ProviderWithHistory>
<div className={classes.root}>
<CssBaseline />
<AppBar style={{ background: '#000000' }}
position="absolute"
className={clsx(classes.appBar, open && classes.appBarShift)}
>
<Toolbar className={classes.toolbar}>
<IconButton
edge="start"
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
className={clsx(
classes.menuButton,
open && classes.menuButtonHidden
)}
>
<MenuIcon />
</IconButton>
<Link to="/" className={classes.navLink}>
<img
className={classes.appBarImage}
src='https://storage.googleapis.com/mems-images/mems-logo-small-rounded.png'
alt="mems logo"
/>
</Link>
<div className={classes.personIcon} style={{ width: '100%', justifyContent: 'flex-end' }}>
<AuthNav />
</div>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
classes={{
paper: clsx(classes.drawerPaper, !open && classes.drawerPaperClose),
}}
open={open}
>
<div className={classes.toolbarIcon}>
<IconButton onClick={handleDrawerClose}>
<ArrowBackIcon style={{ color: 'white' }} />
</IconButton>
</div>
<Divider />
<List>
<ListItem button>
<ListItemIcon>
<SettingsIcon style={{ color: 'white' }} />
<UserSettings />
</ListItemIcon>
<ListItemText primary="Settings" />
</ListItem>
<ListItem button>
<ListItemIcon>
<DashboardIcon style={{ color: 'white' }} />
<Dashboard />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
<ListItem button>
<ListItemIcon>
<MEMslineIcon style={{ color: 'white' }} />
<MEMsLine />
</ListItemIcon>
<ListItemText primary="MEMsLine" />
</ListItem>
<ListItem button>
<ListItemIcon>
<MEMsIcon style={{ color: 'white' }} />
<MEMsGrid />
</ListItemIcon>
<ListItemText primary="All MEMs" />
</ListItem>
<ListItem button>
<ListItemIcon>
<EventIcon style={{ color: 'white' }} />
<p>Events</p>
</ListItemIcon>
<ListItemText primary="Events" />
</ListItem>
<ListItem button>
<ListItemIcon>
<PeopleIcon style={{ color: 'white' }} />
<p>People</p>
</ListItemIcon>
<ListItemText primary="People" />
</ListItem>
<ListItem button>
<ListItemIcon>
<PlaceIcon style={{ color: 'white' }} />
<p>Places</p>
</ListItemIcon>
<ListItemText primary="Places" />
</ListItem>
<ListItem button>
<ListItemIcon>
<MusicIcon style={{ color: 'white' }} />
<p>Music</p>
</ListItemIcon>
<ListItemText primary="Music" />
</ListItem>
<ListItem button>
<ListItemIcon>
<MovieIcon style={{ color: 'white' }} />
<p>Movies</p>
</ListItemIcon>
<ListItemText primary="Movies" />
</ListItem>
<ListItem button>
<ListItemIcon>
<TVIcon style={{ color: 'white' }} />
<p>TV Shows</p>
</ListItemIcon>
<ListItemText primary="TV Shows" />
</ListItem>
<ListItem button>
<ListItemIcon>
<GameIcon style={{ color: 'white' }} />
<p>Games</p>
</ListItemIcon>
<ListItemText primary="Games" />
</ListItem>
</List>
<Divider />
</Drawer>
<main className={classes.content}>
<div className={classes.appBarSpacer} />
<Container maxWidth="lg" className={classes.container}>
<Modal isOpen={loginOpened} onRequestClose={this.closeModal("login")}>
<h1>Login</h1>
<button onClick={this.openModal("signup")}>Open Signup</button>
<button onClick={this.closeModal("login")}>Close this modal</button>
</Modal>
<Modal isOpen={signupOpened} onRequestClose={this.closeModal("signup")}>
<h1>Sign Up</h1>
<button onClick={this.openModal("login")}>Open Login</button>
<button onClick={this.closeModal("signup")}>Close this modal</button>
</Modal>
<button onClick={this.openModal("login")}>Open Login</button>
<button onClick={this.openModal("signup")}>Open Signup</button>
<Box pt={4}>
<Copyright />
</Box>
</Container>
</main>
</div>
</Auth0ProviderWithHistory>
</Router >
// )}
// no={() => <Redirect to="/" />}
// />
// )}
// </AuthConsumer>
);
}
}
export default UserAccount
非常欢迎任何指点!
- 我建议您尝试学习更多关于 React 本身的基础知识 and/or javascript。所以我的建议是多读书,从简单的东西开始,然后转向复杂的东西。
- class 组件应始终具有渲染方法,并将状态保持为 属性,如下例所示。另外,请注意函数切换被写为
toggle = () =>{}
而不是toggle = () => () =>{}
<- 因为这意味着您要返回一个函数而不是仅仅打开函数 body(learn more about arrow functions)
class ClassComponent extends React.Component {
state = {
show: false
};
toggle = () => {
const { show } = this.state;
this.setState({ show: !show });
};
render() {
const { show } = this.state;
return (
<div>
<span>{show ? "Show Class" : "Hide Class"}</span>
<button onClick={this.toggle}>Click here</button>
</div>
);
}
}
- 一个功能组件,过去无法保持状态,但现在可以通过 React hooks 保持状态,如下例所示。
function FunctionComponent(props) {
const [show, setShow] = React.useState(false);
const toggle = () => setShow(!show);
return (
<div>
<span>{show ? "Show Function" : "Hide Function"}</span>
<button onClick={toggle}>Click here</button>
</div>
);
}
了解了这一点后,现在您可以通过以下方式修复您的代码库:
- 您在 class 组件中的渲染方法包含钩子,这是一个 nono,因为钩子可以并且只能与功能组件一起使用
- 您的 class 函数正在返回函数,而不是仅仅让函数被调用,因此当您执行
this.closeModal("login")
时,您必须像this.closeModal("login")()
一样再次调用它,然后它会起作用.
总而言之,hooks 只能用在函数组件中,它们提供的功能与 class 组件所具有的相同。您可以设置状态,列出一些生命周期方法等等。由于功能组件过去仅用于渲染,现在可能会执行一些简单的逻辑,因此它们可以像 class 组件一样使用。
Link 带有工作示例的代码沙箱是 here。
通过阅读和理解状态和生命周期以及反应钩子,我设法弄清楚如何让它工作。
首先我将 const 类 = useStyles() 修改为 const { 类 } = this.props。我还简化了代码并删除了 handleDrawerOpen 和 handleDrawerClose。
我的最终代码如下所示:
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { useAuth0 } from "@auth0/auth0-react";
import LogoutButton from "../Logout-Button";
import LoginButton from "../Login-Button";
import { Nav } from "react-bootstrap";
import Modal from "react-modal";
import Auth0ProviderWithHistory from '../../auth0-provider-with-history'
import UserSettings from "./UserSettings";
import Dashboard from "./Dashboard/Dashboard";
import MEMsLine from "./MemsLine";
import MEMsGrid from "./MemsGrid";
import Copyright from "../Copyright";
import { withStyles } from '@material-ui/core/styles'
import {
Box,
List,
Divider,
Container,
ListItem,
ListItemIcon,
} from '@material-ui/core'
import {
Dashboard as DashboardIcon,
History as MEMsIcon,
People as PeopleIcon,
Place as PlaceIcon,
Cake as EventIcon,
LibraryMusic as MusicIcon,
Tv as TVIcon,
LocalMovies as MovieIcon,
SportsEsports as GameIcon,
Timeline as MEMslineIcon,
Settings as SettingsIcon,
} from '@material-ui/icons'
const useStyles = theme => ({
root: {
display: 'flex',
flexDirection: 'column',
},
titleBar: {
display: 'flex',
width: '100%',
alignItems: 'center',
background: '#000000',
position: "absolute",
},
titleBarImage: {
marginLeft: '0px',
marginTop: '7px',
maxHeight: '75px',
paddingRight: '20px',
},
mainContainer: {
display: 'flex',
width: '100%',
flexDirection: 'row',
},
menuBar: {
marginTop: '77px',
position: 'relative',
whiteSpace: 'nowrap',
backgroundColor: 'black',
color: 'white',
width: '60px',
},
content: {
display: 'flex',
flexWrap: 'nowrap',
flexGrow: 5,
marginTop: '90px',
height: '92vh',
padding: '10px',
},
modal: {
display: 'flex',
flexWrap: 'nowrap',
justifyContent: 'center',
alignItems: 'center',
},
container: {
display: 'flex',
flexDirection: 'column',
flexWrap: 'nowrap',
justifyContent: 'flex-end',
height: '91vh',
},
paper: {
padding: theme.spacing(2),
display: 'flex',
overflow: 'auto',
flexDirection: 'column',
},
navLink: {
textDecoration: 'none',
color: 'inherit',
},
personIcon: {
background: '#000000',
display: 'flex',
flexDirection: 'row',
},
})
class UserAccount extends Component {
state = {
dashboardOpened: true,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
};
openModal = modalType => () => {
if (modalType === "dashboard") {
this.setState({
dashboardOpened: true,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "memsline") {
this.setState({
dashboardOpened: false,
memslineOpened: true,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "mems") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: true,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "events") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: true,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "people") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: true,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "places") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: true,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "music") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: true,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "movies") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: true,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "tvshows") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: true,
gamesOpened: false,
settingsOpened: false
});
} else if (modalType === "games") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: true,
settingsOpened: false
});
} else if (modalType === "settings") {
this.setState({
dashboardOpened: false,
memslineOpened: false,
memsOpened: false,
eventsOpened: false,
peopleOpened: false,
placesOpened: false,
musicOpened: false,
moviesOpened: false,
tvshowsOpened: false,
gamesOpened: false,
settingsOpened: true
});
}
};
closeModal = modalType => () => {
if (modalType === "dashboard") {
this.setState({
dashboardOpened: false
});
} else if (modalType === "memsline") {
this.setState({
memslineOpened: false
});
} else if (modalType === "mems") {
this.setState({
memslineOpened: false
});
}
else if (modalType === "events") {
this.setState({
memslineOpened: false
});
} else if (modalType === "people") {
this.setState({
memslineOpened: false
});
} else if (modalType === "places") {
this.setState({
memslineOpened: false
});
} else if (modalType === "music") {
this.setState({
memslineOpened: false
});
} else if (modalType === "movies") {
this.setState({
memslineOpened: false
});
} else if (modalType === "tvshows") {
this.setState({
memslineOpened: false
});
} else if (modalType === "games") {
this.setState({
memslineOpened: false
});
} else if (modalType === "settings") {
this.setState({
memslineOpened: false
});
}
};
render() {
const { dashboardOpened, memslineOpened, memsOpened, eventsOpened, peopleOpened, placesOpened, musicOpened, moviesOpened, tvshowsOpened, gamesOpened, settingsOpened } = this.state;
const { classes } = this.props
const AuthNav = () => {
const { isAuthenticated } = useAuth0();
return (
<Nav className="justify-content-end">
{isAuthenticated ? <LogoutButton /> : <LoginButton />}
</Nav>
);
};
const modalStyle = {
overlay: {
position: 'absolute',
top: '95px',
bottom: '70px',
left: '50%',
marginLeft: '35px',
marginRight: 'auto',
transform: 'translate(-50%, -0%)',
backgroundColor: 'rgba(255, 255, 255, 0)',
maxWidth: '1500px',
border: 'none',
},
content: {
position: 'absolute',
top: '0px',
left: '0px',
right: '0px',
bottom: '0px',
background: '#fff',
overflow: 'auto',
WebkitOverflowScrolling: 'touch',
padding: '10px',
maxWidth: '1200px',
border: 'none',
}
};
return (
<>
<Auth0ProviderWithHistory>
<div className={classes.root}>
<div className={classes.titleBar}>
<Link to="/" className={classes.navLink}>
<img
className={classes.titleBarImage}
src='https://storage.googleapis.com/mems-images/mems-logo-small-rounded.png'
alt="mems logo"
/>
</Link>
<div className={classes.personIcon} style={{ width: '100%', justifyContent: 'flex-end' }}>
<AuthNav />
</div>
</div>
<div className={classes.mainContainer}>
<List className={classes.menuBar}>
<ListItem button id="dashboardIcon" style={{ backgroundColor: 'black' }}>
<ListItemIcon>
<DashboardIcon onClick={this.openModal("dashboard")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button id="memslineIcon" style={{ backgroundColor: 'black' }}>
<ListItemIcon>
<MEMslineIcon onClick={this.openModal("memsline")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<MEMsIcon onClick={this.openModal("mems")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<EventIcon onClick={this.openModal("events")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<PeopleIcon onClick={this.openModal("people")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<PlaceIcon onClick={this.openModal("places")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<MusicIcon onClick={this.openModal("music")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<MovieIcon onClick={this.openModal("movies")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<TVIcon onClick={this.openModal("tvshows")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<GameIcon onClick={this.openModal("games")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
<ListItem button>
<ListItemIcon>
<SettingsIcon onClick={this.openModal("settings")} style={{ color: 'white' }} />
</ListItemIcon>
</ListItem>
</List>
<Divider />
<div id="content" className={classes.content}>
<div id="modal" className={classes.modal}></div>
<Container maxWidth="lg" className={classes.container}>
<Box pt={4}>
<Copyright />
</Box>
</Container>
</div>
</div>
</div>
<Modal
isOpen={dashboardOpened}
onRequestClose={this.closeModal("dashboard")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"dashboard"}
>
<Dashboard />
</Modal>
<Modal
isOpen={memslineOpened}
onRequestClose={this.closeModal("memsline")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"memsline"}
>
<MEMsLine />
</Modal>
<Modal
isOpen={memsOpened}
onRequestClose={this.closeModal("mems")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"mems"}
>
<MEMsGrid />
</Modal>
<Modal
isOpen={eventsOpened}
onRequestClose={this.closeModal("events")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"events"}
>
<h2>Events</h2>
</Modal>
<Modal
isOpen={peopleOpened}
onRequestClose={this.closeModal("people")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"people"}
>
<h2>People</h2>
</Modal>
<Modal
isOpen={placesOpened}
onRequestClose={this.closeModal("places")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"places"}
>
<h2>Places</h2>
</Modal>
<Modal
isOpen={musicOpened}
onRequestClose={this.closeModal("music")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"music"}
>
<h2>Music</h2>
</Modal>
<Modal
isOpen={moviesOpened}
onRequestClose={this.closeModal("movies")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"movies"}
>
<h2>Movies</h2>
</Modal>
<Modal
isOpen={tvshowsOpened}
onRequestClose={this.closeModal("tvshows")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"tv shows"}
>
<h2>TV Shows</h2>
</Modal>
<Modal
isOpen={gamesOpened}
onRequestClose={this.closeModal("games")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"games"}
>
<h2>Games</h2>
</Modal>
<Modal
isOpen={settingsOpened}
onRequestClose={this.closeModal("settings")}
parentSelector={() => document.querySelector('#modal')}
shouldFocusAfterRender={false}
style={modalStyle}
ariaHideApp={false}
contentLabel={"settings"}
>
<UserSettings />
</Modal>
</Auth0ProviderWithHistory>
</>
)
}
}
export default withStyles(useStyles)(UserAccount)
这是实现我所追求的目标的一种相对简单的方法,我确信使用代码可以更高效,但它正在按我希望的方式工作,并且我在此过程中学到了很多东西方式!