0

I'm new to learning react and I'm trying to understand hooks but keep coming unstuck with the Rules of Hooks.

I have an app that I'm building where it has a navigation bar down the left hand side with icons that open a modal when clicked on:

enter image description here

I'm now trying to set up the 'modal wrapper' to contain each of the modals using this codesandbox as an example (from this stack overflow answer), however I'm running into issues with the Rules of Hooks and coming unstuck.

I've been reading up about reach hooks in the documentation here and understand the theory of only calling hooks at the top level and in functions but as there are quite a few hooks in my code, I'm getting confused between which hooks should be called where and how to then link back to them.

I'm also a bit confused by the uses of classes vs. functions as the example I'm trying to follow makes us of a class and I'm used to coding using functions.

My current code is below:

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

Any pointers very welcome!

Sean
  • 494
  • 6
  • 23
  • React hooks only works with functional component. You need to study more before jumping on the code. You better read https://reactjs.org/docs/hooks-intro.html this and understand how does hook works. Plus how you can relate hook with lifecycle methods. – Monzoor Tamal Jul 26 '20 at 20:31
  • If you'd read my question fully you would see that I have been reading those documents (I linked to them) and studying. Where I'm struggling is putting the theory into practice. – Sean Jul 26 '20 at 20:38
  • But there is a problem of understanding. Otherwise you will not use `const [open, setOpen] = React.useState(false)` in render method. Please practice with small components. And understand how does it works. – Monzoor Tamal Jul 26 '20 at 20:42
  • You’re probably going too fast into learning these things. You have mixed things up in your render method and function aren’t written the way you expect them to work. – Second Son Jul 26 '20 at 21:33
  • to create a modal in react you need to do it using portal and link is [here](https://reactjs.org/docs/portals.html) learn about props and props.children – Ashwin Rao K Jul 26 '20 at 20:31

2 Answers2

1
  1. I'd advise you to try learning more about the basics of React itself and/or javascript. So my suggestion would be to go a read more, start with simple stuff then move to complex ones.
  1. A class component should always have a render method and will hold the state as a property like the example below. Also, notice that the function toggle is written as toggle = () =>{} not toggle = () => () =>{} <- as this would mean you're returning a function instead of just opening the function 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>
        );
      }
    }
  1. A functional component, which in the past did not have the possibility to hold a state but now can through thanks to React hooks, as seen in the example below.
    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>
      );
    }

Now after understanding this bit this is how you can fix your codebase:

  1. Your render method in a class component contains hooks, that is a nono as hooks can and may only be used with functional components
  2. Your class functions are returning functions instead of just letting the function to be called, so when you do this.closeModal("login") you have to call it again like this.closeModal("login")() then it will work.

In summary, hooks can only be used in function components, they provide the same functionalities has class components have. You can set the state, listed to some lifecycle methods, and much more. As function components used to be used in the past just for rendering and probably do some simple logic now they can be used the same way a class component would.

Link the code sandbox with a working example is here.

Second Son
  • 1,481
  • 1
  • 15
  • 26
  • Thank you for taking the time to look at this, I have done more reading and have worked out a solution. Firstly I amended `const classes = useStyles()` to `const { classes } = this.props`. I also simplified the code and removed the `handleDrawerOpen` and `handleDrawerClose`. – Sean Jul 27 '20 at 22:00
0

By doing some more reading and understanding state and lifecycles, and react hooks I managed to figure out how to get this working.

Firstly I amended const classes = useStyles() to const { classes } = this.props. I also simplified the code and removed the handleDrawerOpen and handleDrawerClose.

My final code looks as follows:

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)

This is a relatively simplistic way of achieving what I'm after and I'm sure it's possible to be much more efficient with the code, but it's working how I'd hoped and I have learnt a lot along the way!

Sean
  • 494
  • 6
  • 23
  • There are still some issues with your code. 1. It isn't dry. You are repeating the Modal so many times while it should be written once as a child component and you could just pass props to specify what you want. same goes for the `if` and `esle-if` and the state. This is prone to so many bugs. 2. You still to read a bit more about hooks, I see you are using `useStyles` this naming convention is reserved to hooks 3. As suggested by others it is very clear that you are jumping steps you want to build something big before learning the basics. So learn the basics very well first. A for effort. – Second Son Jul 28 '20 at 09:26
  • Thank you, you are not wrong! I'm going to see if I can start to break my code down into components and make better use of `props`. Doing the reading helps but I find, for me, the best way to learn is to get something working and then to refine the code. – Sean Jul 28 '20 at 16:33
  • My plan to improve the code is to firstly create an object (`activeModal`) that stores the active modal and stores it in state. I'm going to rewrite `openModal` and `closeModel` to update `activeModal` and then `setState`. I'll update the `onClick` for each button to also `setState`. Lastly, I will do as you suggest and not repeat `Modal` and pass `props` into it to specify what I want. – Sean Jul 28 '20 at 20:04