How to display a common component for all routes in react - reactjs

I am new to react js and i'm trying to create a dashboard layout where i want to render a sidebar(which will be common in all the routes) and based upon the click event of sidebar items i want to render different component. Although i have achieved this, but in first instance the sidebar is present with the loaded component but once i refresh the page, only the newly loaded component remains on the page and sidebar is vanished.
//This is my main page code;
import React, { Component } from 'react';
import './Dashboard.css'
import Header from "../Header/Header";
import Footer from "../Footer/Footer";
import Sidebar from "../SideBar/Sidebar";
import Charts from "../Charts/Charts";
import About from "../About/About"
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
class Dashboard extends Component {
constructor(props) {
super(props)
}
render() {
// this.state.aboutComponent = this.props.aboutComponent;
return (
<Router>
<div>
<Sidebar></Sidebar>
<Switch>
<Route exact path={"/"} component={Charts} />
<Route exact path={"/about"} component={About} />
</Switch>
<Footer></Footer>
</div>
</Router>
)
}
}
export default Dashboard
import React from 'react';
import clsx from 'clsx';
import './Sidebar.css';
import { makeStyles, useTheme } from '#material-ui/core/styles';
import Drawer from '#material-ui/core/Drawer';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import List from '#material-ui/core/List';
import Divider from '#material-ui/core/Divider';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
import DeleteIcon from '#material-ui/icons/Delete';
import ChevronLeftIcon from '#material-ui/icons/ChevronLeft';
import ChevronRightIcon from '#material-ui/icons/ChevronRight';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import InboxIcon from '#material-ui/icons/MoveToInbox';
import MailIcon from '#material-ui/icons/Mail';
import Button from '#material-ui/core/Button';
import Menu from '#material-ui/core/Menu';
import MenuItem from '#material-ui/core/MenuItem';
import InfoIcon from '#material-ui/icons/Info';
import About from '../About/About';
// import { Link } from "react-router-dom";
import { useHistory } from "react-router-dom";
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
},
link: {
textDecoration: 'none',
color: theme.palette.text.primary
},
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,
},
hide: {
display: 'none',
},
drawer: {
width: drawerWidth,
flexShrink: 0,
whiteSpace: 'nowrap',
},
drawerOpen: {
width: drawerWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
drawerClose: {
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
width: theme.spacing(7) + 1,
[theme.breakpoints.up('sm')]: {
width: theme.spacing(9) + 1,
},
},
toolbar: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
},
}));
export default function Sidebar() {
const classes = useStyles();
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const [component, setComponent] = React.useState('user')
const [anchorEl, setAnchorEl] = React.useState(null);
const history = useHistory();
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
// <Router>
<div className={classes.root}>
<AppBar
position="fixed"
className={clsx(classes.appBar, {
[classes.appBarShift]: open,
})}
>
<Toolbar>
<h1>SGGB</h1>
<div className="alignment">
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
<h4>Menu</h4>
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
className={clsx(classes.drawer, {
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
})}
classes={{
paper: clsx({
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
}),
}}
>
<List>
<ListItem>
<IconButton
className={clsx(classes.menuButton, {
[classes.hide]: !open,
})}
onClick={handleDrawerClose}>
{theme.direction === 'rtl' ? <ChevronRightIcon /> : <ChevronLeftIcon />}
</IconButton>
</ListItem>
<ListItem>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
className={clsx(classes.menuButton, {
[classes.hide]: open,
})}
>
<MenuIcon />
</IconButton>
</ListItem>
<Link to="/about" className={classes.link}>
<ListItem button key="about" >
<ListItemIcon>{<InfoIcon />}</ListItemIcon>
<ListItemText primary="About" />
</ListItem>
</Link>
</List>
</Drawer>
</div >
// </Router>
);
}
I have also referred to this post;
React Router display one component for all routes ( a header)

You have to put the Route component inside a Switch component like this :
<Router>
<div>
<Sidebar></Sidebar>
<Switch>
<Route exact path={"/"} component={Charts} />
<Route exact path={"/about"} component={About} />
</Switch>
<Footer></Footer>
</div>
</Router>

Related

Sign In page won't render in my React.js app

For some reason, I can't get my SignIn page to render when I click it on the Navbar. The route effectively changes to http://localhost:3000/signin, and that route is set up correctly to render my SignIn component, but the Home page stays the same and the SignIn button changes to "loading...". I'm using google authentication for the SignIn component, and I'm using an AuthCheck fallback and Suspense fallback in my Navbar.
NAVBAR CODE:
import React, { Suspense } from "react";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import Button from "#material-ui/core/Button";
import Logo from '../assets/images/basketball.png';
import { Link } from 'react-router-dom';
import {AuthCheck} from 'reactfire'
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
logo: {
height: "50px",
},
link: {
color: "black",
textDecoration: "none",
},
}));
export const Navbar = () => {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar style={{ alignItems: "center", justifyContent: "center", backgroundColor: "rgb(0, 255, 225)" }}>
<Link to="/">
<img src={Logo} alt="Logo" className={classes.logo} />
</Link>
<Typography style={{flexDirection: 'column', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'black' }} variant="h2" className={classes.title}>
NBA Stat Reference
</Typography>
<Suspense fallback={'loading...'}>
<AuthCheck fallback={
<Button style={{color: "black"}}>
<Link className={classes.link} to="/signin">Sign In</Link>
</Button>
}>
<Button color="black">
<Link className={classes.link} to="/">Home</Link>
</Button>
<Button color="black">
<Link className={classes.link} to="/dashboard">Dashboard</Link>
</Button>
<Button color="black">
<Link className={classes.link} to="/about">About</Link>
</Button>
</AuthCheck>
</Suspense>
</Toolbar>
</AppBar>
</div>
);
}
SIGN IN CODE:
import React, { useState } from 'react'
import firebase from 'firebase/app';
import { AuthCheck, useAuth } from 'reactfire';
import 'firebase/auth';
import { Input } from './Input';
import { Container, Button, makeStyles, Typography, Snackbar, } from '#material-ui/core';
import { withRouter } from "react-router-dom";
import MuiAlert from '#material-ui/lab/Alert';
import { Navbar } from './Navbar'
const Alert = (props) => {
return <MuiAlert elevation={6} variant="filled" {...props} />
}
const useStyles = makeStyles({
googleButton:{
backgroundColor: 'rgb(66,133,244)',
marginTop: '2em',
padding: '0',
color: 'white',
height: '50px',
width: '240px',
border: 'none',
textAlign: 'center',
boxShadow: 'rgb(0 0 0 / 25%) 0px 2px 4px 0px',
fontSize: '16px',
lineHeight: '48px',
display: 'block',
borderRadius: '1px',
fontFamily: 'Roboto, arial, sans-serif',
cursor: 'pointer'
},
googleLogo:{
width: '48px',
height: '48px',
display: 'block'
},
typographyStyle: {
fontFamily: 'Roboto, arial, sans-serif;',
textAlign: 'center',
fontSize: '2em'
},
containerStyle: {
marginTop: '2em'
},
snackBar: {
color: 'white',
backgroundColor: '#4caf50'
}
});
export const SignIn = withRouter((props) => {
const auth = useAuth();
const classes = useStyles();
const { history } = props;
const [open, setOpen] = useState(false);
const handleSnackOpen = () => {
setOpen(true)
};
const handleSnackClose = (event, reason) => {
if (reason === "clickaway") {
return;
}
setOpen(false);
history.push("/");
};
const sign_in = async () => {
const response = await auth.signInWithPopup( new firebase.auth.GoogleAuthProvider());
if(response.user){
handleSnackOpen();
}
};
const sign_out = async () => {
await auth.signOut();
}
return (
<div>
<Navbar />
<Container maxWidth = 'sm' className={classes.containerStyle}>
<Typography className={classes.typographyStyle}>Sign In Below</Typography>
<form>
<div>
<label htmlFor="email">Email</label>
<Input name="email" placeholder="Place Email Here" />
</div>
<div>
<label htmlFor="password">Password</label>
<Input name="password" placeholder="Place Password Here" />
</div>
<Button type="submit" variant='contained' color='primary'>Submit</Button>
</form>
<AuthCheck fallback={
<Button className={classes.googleButton} onClick={sign_in}>Sign In With Google</Button>
}>
<Button variant='contained' color='secondary' onClick={sign_out}>Sign Out</Button>
</AuthCheck>
<Snackbar message={'Success'} open={open} autoHideDuration={6000} onClose={handleSnackClose}>
<Alert onClose={handleSnackClose} severity="success">
Successful Sign In - Redirect in 6 seconds
</Alert>
</Snackbar>
</Container>
</div>
)
});
INDEX.JS (ROUTES)
import React from 'react';
import ReactDOM from 'react-dom';
import {Home} from './client/components/Home';
import {About} from './client/components/About';
import {Dashboard} from './client/components/Dashboard';
import {SignIn} from './client/components/SignIn'
import './index.css'
import {
BrowserRouter as Router,
Route,
Switch
} from "react-router-dom";
import {firebaseConfig} from './firebaseConfig';
import {FirebaseAppProvider, AuthCheck} from 'reactfire';
import 'firebase/auth';
import {Provider} from 'react-redux';
import {store} from './client/Redux/store';
import * as ReactDOMClient from 'react-dom/client';
const root = ReactDOMClient.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<FirebaseAppProvider firebaseConfig={firebaseConfig} suspense={true}>
<Provider store={store}>
<Router>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
<Route path="/signin">
<SignIn />
</Route>
</Switch>
</Router>
</Provider>
</FirebaseAppProvider>
</React.StrictMode>
);

Material UI persistent drawer - content body not resizing

I have an application with a persistent drawer. The drawer contains linked routes to various other components.
In general the drawer itself works fine, but the loaded components are not resizing, when the drawer opens or closes.
In the samples on the mui doc pages this functionality in implemented in the styled main component. Means the content is in the same component as the drawer. This is different in my app, where i have an index file with the routes, a navigationbar file with the drawer and the other components with their respective files.
So, how do i implement this resizing with loaded components?
index.tsx
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import NavigationBar from "./ADBPM-Components/NavigationBar";
import Login from "./login";
import PrivateRoute from "./login/PrivateRoute";
import Authenticator from "./login/auth";
import NotFound from "./notFound";
import WelcomeScreen from "./welcomeScreen";
import Test from "./test";
//Check if already authenticated
Authenticator.refreshState(() => {
refreshPage();
});
export const refreshPage = () => {
ReactDOM.render(
<Router>
<div>
<PrivateRoute noRedirect path="/" component={NavigationBar} />
<Switch>
<PrivateRoute exact path="/" component={WelcomeScreen} />
<PrivateRoute path="/test" component={Test} />
<PrivateRoute path="/changepass" component={ChangePassword} />
<PrivateRoute path="/createuser" component={CreateUser} />
<Route path="/login" component={Login} />
<Route path="/signup" component={CreateUser} />
<PrivateRoute path="/" component={NotFound} />
</Switch>
</div>
</Router>,
document.getElementById("app")
);
};
NavigationBar.tsx
import * as React from "react";
import { withRouter } from "react-router";
import { Link } from "react-router-dom";
import { Divider } from "#material-ui/core";
import Box from '#mui/material/Box';
import Toolbar from '#mui/material/Toolbar';
import Typography from '#mui/material/Typography';
import IconButton from '#mui/material/IconButton';
import MenuIcon from '#mui/icons-material/Menu';
import Drawer from '#mui/material/Drawer';
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '#mui/material/AppBar';
import { styled, useTheme } from '#mui/material/styles';
import List from '#mui/material/List';
import ListItem from '#mui/material/ListItem';
import ListItemIcon from '#mui/material/ListItemIcon';
import ChevronLeftIcon from '#mui/icons-material/ChevronLeft';
import ChevronRightIcon from '#mui/icons-material/ChevronRight';
import ListItemText from '#mui/material/ListItemText';
import CssBaseline from '#mui/material/CssBaseline';
import PeopleIcon from '#mui/icons-material/People';
import QueryStatsIcon from '#mui/icons-material/QueryStats';
import BuildIcon from '#mui/icons-material/Build';
import RequestPageIcon from '#mui/icons-material/RequestPage';
import LogoutOutlinedIcon from '#mui/icons-material/LogoutOutlined';
import PasswordIcon from '#mui/icons-material/Password';
import SupervisedUserCircleIcon from '#mui/icons-material/SupervisedUserCircle';
import TableViewIcon from '#mui/icons-material/TableView';
import Authenticator from "../login/auth";
import * as pack from "../../package.json";
import { Fragment } from "react";
const drawerWidth = 240;
interface AppBarProps extends MuiAppBarProps {
open?: boolean;
}
const AppBar = styled(MuiAppBar, {
shouldForwardProp: (prop) => prop !== 'open',
})<AppBarProps>(({ theme, open }) => ({
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
...(open && {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: `${drawerWidth}px`,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
}),
}));
const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
justifyContent: 'flex-end',
}));
function NavigationBar() {
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<Fragment>
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar position="fixed" open={open}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
sx={{ mr: 2, ...(open && { display: 'none' }) }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
ADBPM ({pack.version})
</Typography>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }} align="right">
{` Logged in as ${Authenticator.user}`}
</Typography>
</Toolbar>
</AppBar>
<Drawer
sx={{
width: drawerWidth,
flexShrink: 0,
'& .MuiDrawer-paper': {
width: drawerWidth,
boxSizing: 'border-box',
},
}}
variant="persistent"
anchor="left"
open={open}
>
<DrawerHeader>
<IconButton onClick={handleDrawerClose}>
{theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
</IconButton>
</DrawerHeader>
<Divider />
<List>
<ListItem button key='Test' component={Link} to="/test">
<ListItemIcon>
<QueryStatsIcon />
</ListItemIcon>
<ListItemText primary='Test' />
</ListItem>
</List>
<Divider />
<List>
<ListItem button key='Change My Password' component={Link} to="/changepass">
<ListItemIcon>
<PasswordIcon />
</ListItemIcon>
<ListItemText primary='Change My Password' />
</ListItem>
<ListItem button key='LogOut' onClick={() => {Authenticator.logout();}}>
<ListItemIcon>
<LogoutOutlinedIcon />
</ListItemIcon>
<ListItemText primary='LogOut' />
</ListItem>
</List>
</Drawer>
</Box>
<Toolbar />
</Fragment>
);
}
export default withRouter(NavigationBar);
test.tsx
import React from "react";
import { RouteComponentProps } from "react-router";
class Test extends React.Component{
constructor(props: RouteComponentProps){
super(props);
}
render(): JSX.Element {
return (
<div>
<h4>
It is only a Test.
</h4>
</div>
);
}
}
export default Test;
I had a similar problem.
I ended up wrapping the router in a Box element with the styling in the Persistent Drawer demo.
https://codesandbox.io/s/2g979p?file=/demo.js:966-1552
const Main = styled(Box, { shouldForwardProp: (prop) => prop !== 'open' })(
({ theme, open }) => ({
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
marginLeft: `-${drawerWidth}px`,
...(open && {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: 0,
}),
}),
);

How can i set Routing while creating admin panel

I want to show only one component inside a white container that clicked but it is showing all components . how can I create an admin panel with fine routing ???
Like other admin panel, i just want to show proper routing But in my case, both components are displaying
App.js, main file
import { BrowserRouter, Route, Switch } from "react-router-dom"
import Home from "./Components/Home/Home"
import CreateAccount from "./Components/Create-Account/CreateAccount"
import PostRequest from "./Components/Post-request/PostRequest"
import New from "./new"
const App = () => {
return (
<BrowserRouter>
<Home />
<Route exact path="/" component={New} />
<Switch >
<Route exact path="/createAccount" component={CreateAccount} />
<Route exact path="/postRequests" component={PostRequest} />
</Switch>
</BrowserRouter>
)
}
export default App
And the Home page Component
import React from 'react';
import clsx from 'clsx';
import "./home.css"
import PostRequest from "../Post-request/PostRequest"
import CreateAccount from "../Create-Account/CreateAccount"
import { SidebarData } from "./sideBarData"
import { Link } from "react-router-dom"
import { makeStyles, useTheme } from '#material-ui/core/styles';
import Drawer from '#material-ui/core/Drawer';
import CssBaseline from '#material-ui/core/CssBaseline';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import List from '#material-ui/core/List';
import Typography from '#material-ui/core/Typography';
import Divider from '#material-ui/core/Divider';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
import ChevronLeftIcon from '#material-ui/icons/ChevronLeft';
import ChevronRightIcon from '#material-ui/icons/ChevronRight';
const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
},
appBar: {
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
},
appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
},
menuButton: {
marginRight: theme.spacing(2),
},
hide: {
display: 'none',
},
drawer: {
width: drawerWidth,
flexShrink: 0,
},
drawerPaper: {
width: drawerWidth,
},
drawerHeader: {
display: 'flex',
alignItems: 'center',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
justifyContent: 'flex-end',
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
marginLeft: -drawerWidth,
},
contentShift: {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: 0,
},
}));
export default function PersistentDrawerLeft() {
const classes = useStyles();
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<div className={classes.root}>
<CssBaseline />
<AppBar
position="fixed"
className={clsx(classes.appBar, {
[classes.appBarShift]: open,
})}
>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
className={clsx(classes.menuButton, open && classes.hide)}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap>
Master Panel
</Typography>
</Toolbar>
</AppBar>
<Drawer
className={classes.drawer}
variant="persistent"
anchor="left"
open={open}
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.drawerHeader}>
<IconButton onClick={handleDrawerClose}>
{theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
</IconButton>
</div>
<Divider />
<List>
<ul>
<h2>Admin</h2>
{SidebarData.map((item, index) => {
return (
<div>
<li key={index} className={item.cName}>
<Link className="textClass" to={item.path}>
<div className="listItem_Alignment container">
<span>{item.icon}</span>
<span className="titleLeftMargin">{item.title}</span>
</div>
</Link>
</li>
</div>
)
})}
</ul>
</List>
<Divider />
</Drawer>
<main
className={clsx(classes.content, {
[classes.contentShift]: open,
})}
>
<div className={classes.drawerHeader} />
<CreateAccount />
<PostRequest />
</main>
</div>
);
}
You can use nested routing for your admin panel. You take reference of below link.
Nested routing example

Conditional Rendering in Nextjs & TypeScript not working

Trying to render a component conditionally. I have a drawHelper variable & a function to toggle it true or false. The component renders or not based on the initial value of drawHelper. (false, doesn't render, true it does).
The toggle function changes the value. I checked with console.log(drawHelper) But changing the value does not make the component appear or disappear.
Am I missing something here?
import React from 'react';
import AppBar from '#material-ui/core/AppBar';
import CssBaseline from '#material-ui/core/CssBaseline';
import Divider from '#material-ui/core/Divider';
import Drawer from '#material-ui/core/Drawer';
import Hidden from '#material-ui/core/Hidden';
import IconButton from '#material-ui/core/IconButton';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import DashboardIcon from '#material-ui/icons/Dashboard';
import MenuIcon from '#material-ui/icons/Menu';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import { makeStyles, useTheme, Theme, createStyles } from '#material-ui/core/styles';
import { User } from './User';
import { Draw } from "components/Layout/Countryballs/Draw";
const drawerWidth = 240;
export const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: 'flex',
color: '#fff',
},
drawer: {
[theme.breakpoints.up('sm')]: {
width: drawerWidth,
flexShrink: 0,
},
},
appBar: {
marginLeft: drawerWidth,
[theme.breakpoints.up('sm')]: {
width: `calc(100% - ${drawerWidth}px)`,
},
},
menuButton: {
marginRight: theme.spacing(2),
[theme.breakpoints.up('sm')]: {
display: 'none',
},
},
toolbar: theme.mixins.toolbar,
drawerPaper: {
width: drawerWidth,
backgroundColor: theme.palette.primary.main
},
content: {
flexGrow: 1,
},
menuItem: {
color: '#fff',
},
}),
);
export const Layout: React.FC<LayoutProps> = (props) => {
const { container } = props;
const classes = useStyles();
const theme = useTheme();
const [mobileOpen, setMobileOpen] = React.useState(false);
function handleDrawerToggle() {
setMobileOpen(!mobileOpen);
}
// Display Draw component
// 1 Create property
var drawHelper: Boolean = false;
function toggleDraw() {
console.log(drawHelper);
drawHelper = !drawHelper;
}
const drawer = (
<div>
<div className={classes.toolbar} />
<Divider />
<List>
{['Draw'].map((text) => (
<ListItem button key={text} onClick={toggleDraw} className={classes.menuItem}>
<ListItemIcon className={classes.menuItem}><DashboardIcon /></ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</div>
);
return (
<div className={classes.root}>
<CssBaseline />
<AppBar position="fixed" className={classes.appBar}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
edge="start"
onClick={handleDrawerToggle}
className={classes.menuButton}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap>
Project name
</Typography>
<User/>
</Toolbar>
</AppBar>
<nav className={classes.drawer} aria-label="mailbox folders">
{/* The implementation can be swapped with js to avoid SEO duplication of links. */}
<Hidden smUp implementation="css">
<Drawer // this one is for mobile
container={container}
variant="temporary"
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
open={mobileOpen}
onClose={handleDrawerToggle}
classes={{
paper: classes.drawerPaper,
}}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
>
{drawer}
</Drawer>
</Hidden>
<Hidden xsDown implementation="css">
<Drawer // This one is for desktop
classes={{
paper: classes.drawerPaper,
}}
variant="permanent"
open
>
{drawer}
</Drawer>
</Hidden>
</nav>
<main className={classes.content}>
{/* This is where my components renders */}
{
drawHelper === true && (<Draw/>)
}
<div className={classes.toolbar} />
{props.children}
</main>
</div>
);
}
The variable drawHelper in your code is instantiated on every render. You'd want to use React's state to make sure your drawHelper's value is preserved on the next re-renders.
const [drawHelper, toggleDrawHelper] = React.useState(false)
function toggleDraw() {
toggleDrawHelper(!drawHelper);
}

Drawer Content Change

How to change the content when clicked on different items.
I have two different archives (Home.js and Sidebar.js), in Sidebar I declare the items, but in Home, I put some buttons. But I don't know how to pass the information that I want to change between the items listed in my sidebar.
I am using this Drawer example (https://material-ui.com/demos/drawers/#persistent-drawer).
Project Running
in my app.js i have
import React, { Component } from 'react';
import Footer from './componets/Footer';
import Home from './componets/Home';
import store from './store'
import { Provider } from 'react-redux';
class App extends Component {
render() {
return (
<Provider store={store}>
<div className="content">
<Drawer/>
<Home/>
<Footer/>
</div>
</Provider>
);
}
}
export default App;
In my css file:
.conteudo{
display: grid;
grid-template-areas:
'home home home home'
'home home home home'
'footer footer footer footer'
}
I got a way to do it. But for every button in my drawer, i need to create a function that puts a number in my value. Have a way to declare one function and that every button in my class pass a number to my value?
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { withStyles } from '#material-ui/core/styles';
import Drawer from '#material-ui/core/Drawer';
import CssBaseline from '#material-ui/core/CssBaseline';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import List from '#material-ui/core/List';
import Typography from '#material-ui/core/Typography';
import Divider from '#material-ui/core/Divider';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
import ChevronLeftIcon from '#material-ui/icons/ChevronLeft';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import Button from '#material-ui/core/Button'
import HomeIcon from '#material-ui/icons/Home'
import MeetingRoomIcon from '#material-ui/icons/MeetingRoom'
const drawerWidth = 240;
function Conteudo(props){
return(
<Typography component='div'>
{props.children}
</Typography>
)
}
Conteudo.propTypes ={
children: PropTypes.node.isRequired,
};
const styles = theme => ({
root: {
display: 'flex',
},
appBar: {
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
},
appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
},
menuButton: {
marginLeft: 12,
marginRight: 20,
},
hide: {
display: 'none',
},
drawer: {
width: drawerWidth,
flexShrink: 0,
},
drawerPaper: {
width: drawerWidth,
},
drawerHeader: {
display: 'flex',
alignItems: 'center',
padding: '0 8px',
...theme.mixins.toolbar,
justifyContent: 'flex-end',
},
content: {
flexGrow: 1,
padding: theme.spacing.unit * 3,
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
marginLeft: -drawerWidth,
},
contentShift: {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: 0,
},
});
class PersistentDrawerLeft extends React.Component {
state = {
open: false,
value: 0
};
handleDrawerOpen = () => {
this.setState({ open: true });
};
handleDrawerClose = () => {
this.setState({ open: false });
};
checkEvent = () => {
this.setState({value : 1})
console.log({value : 1})
}
checkEvent1 = () => {
this.setState({value : 0})
console.log({value : 0})
}
handleChange = (event, value) => {
this.setState({ value })
console.log(value)
}
render() {
const { classes, theme } = this.props;
const { open } = this.state;
const { value } = this.state;
return (
<div className={classes.root}>
<CssBaseline />
<AppBar
position="fixed"
className={classNames(classes.appBar, {
[classes.appBarShift]: open,
})}
>
<Toolbar disableGutters={!open}>
<IconButton
color="inherit"
aria-label="Open drawer"
onClick={this.handleDrawerOpen}
className={classNames(classes.menuButton, open && classes.hide)}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" noWrap>
Drawer
</Typography>
</Toolbar>
</AppBar>
<Drawer
value ={value}
className={classes.drawer}
variant="persistent"
anchor="left"
open={open}
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.drawerHeader}>
<IconButton onClick={this.handleDrawerClose}>
<ChevronLeftIcon />
</IconButton>
</div>
<Divider />
<List>
<ListItem button onClick={this.checkEvent1} onChange={this.handleChange}>
<ListItemIcon>
<HomeIcon/>
</ListItemIcon>
<ListItemText primary='Central'/>
</ListItem>
<ListItem button onClick={this.checkEvent} onChange={this.handleChange}>
<ListItemIcon>
<MeetingRoomIcon/>
</ListItemIcon>
<ListItemText primary='BedRoom'/>
</ListItem>
</List>
<Divider />
</Drawer>
<main
className={classNames(classes.content, {
[classes.contentShift]: open,
})}
>
<div className={classes.drawerHeader} onChange={this.handleChange}/>
{value === 0 && <Conteudo> <Button variant="contained" color="primary">Default</Button> </Conteudo>}
{value === 1 && <Conteudo><Button variant="contained" color="secondary">Default</Button> </Conteudo>}
{value === 2 && <Conteudo><Button variant="contained" color="danger">Default</Button> </Conteudo>}
</main>
</div>
);
}
}
PersistentDrawerLeft.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
export default withStyles(styles, { withTheme: true })(PersistentDrawerLeft);

Resources