I am new to React js. I am implementing the drawer (material-ui), so when user clicks on left menu (LeftMenu.jsx); the respective component should get render in the center (i.e, MainContent.jsx)
Unfortunately, I am getting following error:
Error: Invariant failed: You should not use <Link> outside a <Router>
But if I enclosed Link in LeftMenu.jsx then URL changes but view does not get render.
I tried the solutions given in React router changes url but not view but still the problem is not solved.
Following are the list of components:
Status.jsx
import React, { Component } from "react";
class Status extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return <div>Status</div>;
}
}
export default Status;
AdminPanelLayout.jsx
export default function AdminPanelLayout() {
const classes = useStyles();
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
if (open) {
setOpen(false);
} else {
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"
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap>
Admin Panel
</Typography>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
className={clsx(classes.drawer, {
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
})}
classes={{
paper: clsx({
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
}),
}}
>
<div className={classes.toolbar}></div>
<Divider />
<LeftMenu></LeftMenu>
</Drawer>
<MainContent></MainContent>
</div>
);
}
MainContent.jsx
export default function MainContent() {
const classes = useStyles();
return (
<Router>
<main className={classes.content}>
<div className={classes.toolbar} />
<Switch>
<Route path="/Status" component={withRouter(Status)}>
<Status />
</Route>
<Route path="/">
<span>testing</span>
</Route>
</Switch>
</main>
</Router>
);
}
LeftMenu.jsx
export default function LeftMenu() {
return (
<div>
<List>
{["Status", "Starred", "Send email", "Drafts"].map((text, index) => (
<ListItem button key={text} component={Link} to="/Status">
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{["All mail", "Trash", "Spam"].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</div>
);
}
App.js
import "./App.css";
import AdminPanelLayout from "./components/AdminPanelLayout";
import LeftMenu from "./components/LeftMenu";
function App() {
return <AdminPanelLayout></AdminPanelLayout>;
}
export default App;
You should either use
<Route path="/Status" component={Status}>
or
<Route path="/Status">
<Status />
</Route>
Also you should not be doing this component={withRouter(Status)}
because this is equivalent to component={Status}
. The purpose of withRouter
is to get a component which is not rendered via Route
to get access to the route props
. Since Status
is already rendered via Route
wrapping it with withRouter
is not needed.
codesanbox - Hope this helps !