dhavalnc1
dhavalnc1

Reputation: 139

How to render different component onClick using React material-ui Drawer list?

I am working on Dashboard design using React material-ui package. I have an App bar and a Drawer with a List of different items. When I click items in Drawer, I want to render the respective component inside the "main" tag of Drawer.

The App.js component is class-based. And I have functional component for all other routes and features.

import React, { useState } from "react";
import { makeStyles, useTheme } from '@material-ui/core/styles';
import { Link } from 'react-router-dom'
import { useAuthState } from '../contexts/AuthContext';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import DraftsIcon from '@material-ui/icons/Drafts';

import {MenuItem, MenuList, ListItemIcon, ListItemText
        , Drawer, ListItem, List, Divider, CssBaseline
        , Paper, IconButton, Typography, AppBar, Toolbar
        , Button, Input } from '@material-ui/core';

const drawerWidth = 200;

const useStyles = makeStyles(theme => ({
    root: {
      display: 'flex',
    },
    appBar: {
        width: `calc(100% - ${drawerWidth}px)`,
        marginLeft: drawerWidth,
    },
    menuButton: {
      marginRight: theme.spacing(2),
      fontSize: "16px",
      color: "#fff",
    },
    hide: {
        display: 'none',
    },
    drawer: {
        width: drawerWidth,
        flexShrink: 0,
    },
    drawerPaper: {
        width: drawerWidth,
    },
    toolbar: theme.mixins.toolbar,

    content: {
        flexGrow: 1,
        backgroundColor: theme.palette.background.default,
        padding: theme.spacing(3),
    },

    title: {
        flexGrow: 1,
        fontSize: "18px",
    },
    LinkBar: {

    },
    SideBarFont: {
        fontSize: "14px",
    },
}));


export default function Dashboard(props) {
    const classes = useStyles();
    const theme = useTheme();
    const { setUser } = useAuthState();
    const [open, setOpen] = React.useState(false);

    return (
        <div className={classes.root}>
            <CssBaseline />
            <AppBar 
                className={classes.appBar}
                position="fixed"
            >
                <Toolbar>
                    <Typography variant="h6" className={classes.title} noWrap>
                        Dashboard
                    </Typography>

                    <Button color="inherit">Logout</Button>

                </Toolbar>
            </AppBar>

            <Drawer
                className={classes.drawer}
                variant="permanent"
                anchor="left"
                classes={{
                    paper: classes.drawerPaper,
                }}
                >
                <div className={classes.toolbar} />
                <Divider />

                <List component="nav" aria-label="main mailbox folders">
                    <ListItem button>
                        <ListItemIcon>
                            <InboxIcon />
                        </ListItemIcon>

                        <ListItemText disableTypography className={classes.SideBarFont} primary="User" />
                    </ListItem>
                    <ListItem button>
                        <ListItemIcon>
                            <DraftsIcon />
                        </ListItemIcon>

                        <ListItemText disableTypography className={classes.SideBarFont}  primary="Account" />
                    </ListItem>

                    <ListItem button>
                        <ListItemIcon>
                            <DraftsIcon />
                        </ListItemIcon>

                        <ListItemText disableTypography className={classes.SideBarFont}  primary="Customer Support" />
                    </ListItem>

                    <ListItem component={Link} to="/inventory" button>
                        <ListItemIcon>
                            <DraftsIcon />
                        </ListItemIcon>

                        <ListItemText disableTypography className={classes.SideBarFont}  primary="Inventory" />
                    </ListItem>
                </List>

            </Drawer>

            <main className={classes.content}>
                <div className={classes.toolbar} />
                <h1>Hello</h1>
                <Typography paragraph>
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
                    ut labore et dolore magna aliqua. Rhoncus dolor purus non enim praesent elementum
                </Typography>

            </main>           

        </div>
    );
}

I have functional components for Users, Inventory, CustomerSupport, Account in their respective jsx files. How can i render or inside "main" when the user click on Drawer List items?

See below for the UI. I want to render where Hello is rendered.

enter image description here

Upvotes: 3

Views: 8096

Answers (1)

T. Evans
T. Evans

Reputation: 1001

First, you'll need to do a few things.

  1. Create components to render in the main
  2. Import those components into the Dashboard Component

Since you are already using useState in your components, you'll need to set up another useState.

On your ListItem you can add an onClick to the component and do the useState function to set that state to a said component.

In the main you'll need to add some sort of ternary or checker to determine what component to display.

I have removed a number of items here but this is a brief example for you:

import User from '/path/to/user/component';
import Account from '/path/to/account/component';
...
export default function Dashboard(props) {
  const [component, setComponent] = useState('user')
  ...
  return (
    ...
    <ListItem button onClick={() => setComponent('account')}>
      <ListItemIcon>
        <DraftsIcon />
      </ListItemIcon>

      <ListItemText disableTypography className={classes.SideBarFont} primary="Account" />
    </ListItem >
    ...

      <main className={classes.content}>
        <div className={classes.toolbar} />
        {
          component === 'user' ?
          <User />
          :
          component === 'account' ?
          :
          <Account />
          ...
        }
      </main>

    </div>
  );
}

Yes there is a cleaner way to do the component rendering in the main but this should give you an idea of where to start

Upvotes: 4

Related Questions