Making sidebar available for all components | React JS | React Router v6 - javascript

I am using react router dom v6 and want to implement a logic where the sidebar will be available across all the components in my. Currently whenever i try to click any in side bar the side bar is vanishing.
I want to keep the side bar across all the components in my app.
Side Bar available
Sidebar gone
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {BrowserRouter as Router, Routes, Route,Navigate,Link} from
'react-router-dom'; import Login from
'../src/components/Login/LoginPage'; import Test from
'../src/components/test/Test'; import Homepage from
'../src/components/homepage/HomePage'; import Scheduler from
'../src/components/scheduler/Scheduler'; import Classroom from
'../src/components/classroom/Classroom'; import Assignment from
'../src/components/assignment/Assignment'; import Meeting from
'../src/components/meetings/Meetings'; import ReportCard from
'../src/components/reportcard/ReportCard'; import SideMenuBar from
'../src/components/sidemenubar/SideMenuBar'; ReactDOM.render(
<Router>
<Routes>
<Route path='/' element={<Login />} />
<Route path='/api/v1/testpath' element={<Test />} />
{/* Sidebar Routes */}
<Route path="/api/v1/app/userHome" exact element={<Test />} />
<Route path="/api/v1/app/schedule" exact element={<Scheduler />} />
<Route path="/api/v1/app/myclassroom" exact element={<Classroom />} />
<Route
path="/api/v1/app/myassignments"
exact
element={<Assignment />}
/>
<Route path="/api/v1/app/mymeetings" exact element={<Meeting />} />
<Route path="/api/v1/app/viewreports" exact element={<ReportCard />} />
</Routes>
</Router>,
document.getElementById('root')
);
Sidebar.js
import {
ListItemIcon,
ListItemText,
List,
Divider,
Drawer,
Avatar,
Box,
ListItemButton,
} from "#mui/material";
import { makeStyles } from "#mui/styles";
import HomeIcon from "#mui/icons-material/Home";
import WatchLaterIcon from "#mui/icons-material/WatchLater";
import GroupsIcon from "#mui/icons-material/Groups";
import AssignmentOutlinedIcon from "#mui/icons-material/AssignmentOutlined";
import AssessmentOutlinedIcon from "#mui/icons-material/AssessmentOutlined";
import LogoutOutlinedIcon from "#mui/icons-material/LogoutOutlined";
import MeetingRoomOutlinedIcon from "#mui/icons-material/MeetingRoomOutlined";
import Logo from "./logo.png";
import { BrowserRouter as Router, Route, Link, Routes } from "react-router-dom";
import Homepage from "../homepage/HomePage";
import Scheduler from "../scheduler/Scheduler";
import Classroom from "../classroom/Classroom";
import Assignment from "../assignment/Assignment";
import ReportCard from "../reportcard/ReportCard";
import Meeting from "../meetings/Meetings";
const drawerWidth = 350;
const useStyles = makeStyles({
page: {
background: "#f9f9f9",
width: "100%",
},
root: {
display: "flex",
},
drawer: {
width: drawerWidth,
},
drawerPaper: {
width: drawerWidth,
borderRadius: "2%",
},
listitem: {
"&:hover": {
fontWeight: "fontWeightBold",
background: "#f9f9f9",
},
},
navlink: {
textDecoration: "inherit",
color: "inherit",
},
});
export default function Sidemenubar() {
const classes = useStyles();
return (
<Box sx={{ display: "flex" }}>
<Divider />
<Drawer
className={classes.drawer}
variant="permanent"
classes={{ paper: classes.drawerPaper }}
anchor="left"
>
{/*App Logo */}
<Avatar
src={Logo}
alt="404"
sx={{ width: 100, height: 100, alignSelf: "center", margin: 1 }}
/>
{/*Menu Items */}
<List component="nav">
<Link to="/api/v1/app/userHome" className={classes.navlink}>
<ListItemButton
sx={{
"&:hover": {
fontWeight: "bold",
boxShadow: 1,
background: "#6D62DA",
},
}}
>
<ListItemIcon>
<HomeIcon />
</ListItemIcon>
<ListItemText primary="Home" />
</ListItemButton>
</Link>
<Divider />
<Link to="/api/v1/app/schedule" className={classes.navlink}>
<ListItemButton
sx={{
"&:hover": {
fontWeight: "bold",
boxShadow: 1,
background: "#6D62DA",
},
}}
>
<ListItemIcon>
<WatchLaterIcon />
</ListItemIcon>
<ListItemText primary="Scheduler" />
</ListItemButton>
</Link>
<Divider />
</List>
</Drawer>
<Routes>
<Route path='/api/v1/app/userHome' element={<Homepage />}></Route>
<Route path='/api/v1/app/schedule' element={<Scheduler />}></Route>
</Routes>
</Box>
);
}
HomePage.js
import React from 'react';
import { Grid } from "#mui/material";
import SideMenuBar from '../sidemenubar/SideMenuBar';
import HomePage from '../homepage/HomePage';
import Scheduler from '../scheduler/Scheduler';
import {BrowserRouter as Router,
Routes, Route,Navigate,Link} from 'react-router-dom';
class Test extends React.Component{
render(){
return (
<Grid container>
<Grid item md={4}>
<SideMenuBar />
</Grid>
<Grid item md={8}>
<HomePage />
</Grid>
</Grid>
)
}
}
export default Test;

If you want to render a sidebar on every route/page then I suggest:
Using Layout Wrapper Component and Outlet
Create a layout container component that renders the Sidebar component and an Outlet into the respective grid columns. Render the page routes nested into the layout.
import { Outlet } from 'react-router-dom';
import SideMenuBar from '../sidemenubar/SideMenuBar';
const PageLayout = () => (
<Grid container>
<Grid item md={4}>
<SideMenuBar />
</Grid>
<Grid item md={8}>
<Outlet /> // <-- nested routes rendered here
</Grid>
</Grid>
);
index.js
<Router>
<Routes>
<Route path="/" element={<PageLayout />} >
<Route index element={<Login />} />
<Route path="/api/v1/app/userHome" element={<UserHome />} />
<Route path="/api/v1/app/schedule" element={<Scheduler />} />
<Route path="/api/v1/app/myclassroom" element={<Classroom />} />
<Route
path="/api/v1/app/myassignments"
element={<Assignment />}
/>
<Route path="/api/v1/app/mymeetings" element={<Meeting />} />
<Route path="/api/v1/app/viewreports" element={<ReportCard />} />
</Route>
</Routes>
</Router>
Using Wrapper Component and children Prop
An alternative would be to have the PageLayout component render its children instead, and wrap the Routes component.
const PageLayout = ({ children }) => (
<Grid container>
<Grid item md={4}>
<SideMenuBar />
</Grid>
<Grid item md={8}>
{children}
</Grid>
</Grid>
);
index.js
<Router>
<PageLayout>
<Routes>
<Route path="/ element={<Login />} />
<Route path="/api/v1/app/userHome" element={<UserHome />} />
<Route path="/api/v1/app/schedule" element={<Scheduler />} />
<Route path="/api/v1/app/myclassroom" element={<Classroom />} />
<Route
path="/api/v1/app/myassignments"
element={<Assignment />}
/>
<Route path="/api/v1/app/mymeetings" element={<Meeting />} />
<Route path="/api/v1/app/viewreports" element={<ReportCard />} />
</Routes>
</PageLayout>
</Router>

Related

react route function giving me blank page for my home screen

I'm having some trouble wherein adding a route path to my app, it gives me a blank page on my HomeScreen. I add this line below to my app.js
<Route path="/" element={HomeScreen} exact />
Can you guys help?
App.js
import { BrowserRouter as Router, Route } from "react-router-dom";
import { Container } from "react-bootstrap";
import Header from "./components/Header";
import Footer from "./components/Footer";
import HomeScreen from "./screens/HomeScreen";
const App = () => {
return (
<Router>
<Header />
<main className="py-3">
<Container>
<Route path="/" element={HomeScreen} exact />
</Container>
</main>
<Footer />
</Router>
);
};
export default App;
HomeScreen.js
import { Row, Col } from "react-bootstrap";
import Product from "../components/Product";
import products from "../products";
const HomeScreen = () => {
return (
<>
<h1>Latest Photocards</h1>
<Row>
{products.map((product) => (
<Col key={product._id} sm={12} md={6} lg={4} xl={3}>
<Product product={product} />
</Col>
))}
</Row>
</>
);
};
export default HomeScreen;
Wrap Everything between the BrowserRouter tag
<BrowserRouter>
--here--
<BrowserRouter/>
You have to pass JSX element in your Route as:
<Route path="/" element={<HomeScreen />} exact />
Always wrap all your routes within the BrowserRouter and the Routes Components.
Also the JSX element itself must be passed in to your routes.
Please find the modified snippet below.
<Router>
<Header />
<main className="py-3">
<Container>
<Routes>
<Route path="/" element={<HomeScreen />} exact />
<Routes>
</Container>
</main>
<Footer />
</Router>
Here how i use react-router-dom
index.js
import App from './App';
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider>
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
</Provider>
);
App.js
import { Route, Routes } from 'react-router-dom';
function App(){
<>
<NavBar />
<Routes>
<Route path="/">
<Route index={true} element={<Home />} />
</Route>
</Routes>
</>
}
Hope this will solve your issue

navigation in react router dom version 6.3.0 doesn't work proplery

I'm working on react website and I have a problem while navigating to any page
that when I scroll to a certain point in a home page for example then I try to navigate to another page I find the other page is rendered from the the bottom of the page not the top
routes.tsx file
const App: React.FC = () => (
<BrowserRouter>
<Layout className="layout">
<div style={{ marginBottom: "64px" }}>
<Header>
<AppHeader />
</Header>
</div>
<Content>
<div className="site-layout-content">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/offers" element={<Login />} />
<Route path="/aboutUs" element={<AboutUs />} />
<Route path="/contactUs" element={<ContactUs />} />
<Route path="/placeDetails/:id" element={<PlaceDetails />} />
<Route path="/advantages" element={<Advantages />} />
</Routes>
</div>
</Content>
<Footer style={{ textAlign: "center" }}>
<AppFooter />
</Footer>
</Layout>
</BrowserRouter>
);
export default App;
header.tsx
const Index = () => {
const navigate = useNavigate();
return (
<Row className="header">
<Col span={12} className="header__logo">
<div className="header__logo--imgContainer" onClick={() => navigate("/")}>
<img src={logoImg} alt="logo" />
</div>
</Col>
<Col span={12} className="header__menu">
<ul className="ant-menu-overflow ant-menu ant-menu-root ant-menu-horizontal ant-menu-light ant-menu-rtl">
<li className="ant-menu-item">
<span onClick={() => navigate("/offers")}>{strings.header.offers}</span>
</li>
<li className="ant-menu-item">
<span onClick={() => navigate("/advantages")}>{strings.header.services}</span>
</li>
</ul>
</Col>
</Row>
);
};
export default Index;
you can simply use this helper component for this use case:
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function ScrollToTop() {
const { pathname } = useLocation();
useEffect(() => {
// "document.documentElement.scrollTo" is the magic for React Router Dom v6
document.documentElement.scrollTo({
top: 0,
left: 0,
behavior: "instant", // Optional if you want to skip the scrolling animation
});
}, [pathname]);
return null;
}
and then you can change above code like this:
const App: React.FC = () => (
<BrowserRouter>
<ScrollToTop/> // this is new helper component
<Layout className="layout">
<div style={{ marginBottom: "64px" }}>
<Header>
<AppHeader />
</Header>
</div>
<Content>
<div className="site-layout-content">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/offers" element={<Login />} />
<Route path="/aboutUs" element={<AboutUs />} />
<Route path="/contactUs" element={<ContactUs />} />
<Route path="/placeDetails/:id" element={<PlaceDetails />} />
<Route path="/advantages" element={<Advantages />} />
</Routes>
</div>
</Content>
<Footer style={{ textAlign: "center" }}>
<AppFooter />
</Footer>
</Layout>
</BrowserRouter>
);
export default App;
This will reset the scroll position on top whenever route changes.

I'm getting a blank screen with React JS Navigation

I've read some other articles about people facing the same issue but still haven't found anything that works for me. What has me confused is that the Login.js code works when I run it directly without navigation. Likewise, if I change the Login.js code and merely render an H1 tag, it works even with navigation.
AppRouter.js
class AppRouter extends Component {
render() {
return (
<BrowserRouter>
<div>
<Navigation />
<Routes>
<Route exact path="/" element={<Home/>}/>
<Route exact path="/login" element={<Login/>}/>
<Route component={Error}/>
</Routes>
</div>
</BrowserRouter>
);
}
}
export default AppRouter;
Navigation.js
import React from 'react';
import { NavLink } from 'react-router-dom';
const Navigation = () => {
return (
<div>
<NavLink to="/">Home</NavLink>
<NavLink to="/login">Login</NavLink>
</div>
);
}
export default Navigation;
Login.js
export default function Login(){
{
return (
<>
<Header/>
<Flex
minH={'100vh'}
align={'center'}
justify={'center'}
bg={useColorModeValue('gray.50', 'gray.800')}>
<Stack spacing={8} mx={'auto'} maxW={'lg'} py={12} px={8}>
<Stack align={'center'}>
<Heading fontSize={'4xl'}>Sign in to your account</Heading>
<Text fontSize={'lg'} color={'gray.600'}>
Welcome!<Link color={'blue.400'}>features</Link>
</Text>
</Stack>
<Box
rounded={'lg'}
bg={useColorModeValue('white', 'gray.700')}
boxShadow={'lg'}
p={8}>
<Stack spacing={4}>
<FormControl id="email">
<FormLabel>Email address</FormLabel>
<Input type="email" />
</FormControl>
<FormControl id="password">
<FormLabel>Password</FormLabel>
<Input type="password" />
</FormControl>
<Stack spacing={10}>
<Stack
direction={{ base: 'column', sm: 'row' }}
align={'start'}
justify={'space-between'}>
<Checkbox>Remember me</Checkbox>
<Link color={'blue.400'}>Forgot password?</Link>
</Stack>
<Button
bg={'blue.400'}
color={'white'}
_hover={{
bg: 'blue.500',
}}>
Sign in
</Button>
</Stack>
</Stack>
</Box>
</Stack>
</Flex>
</>
)
}
}
App.js
function App() {
return (
<AppRouter/>
);
}
Try this!
class AppRouter extends Component {
render() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login/>}/>
<Route path="/Error" element={<div>Error Message</div>} />
<Route path="*" element={<Navigate to="/Error" />} />
</Routes>
</BrowserRouter>
);
}
}
export default AppRouter;
Codesandbox Example

how to render different components using react-router-dom v6.0.0 with react-redux

i am trying to render different components by clicking on a link but the problem is the url updates and the ui remains same unchanged, everytime i click on different item to render but the same thing happens, i tried a lot to fix it but i can not find a solution for this.
starting from index.js as entry point
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import store from "./Components/store";
import { Provider } from "react-redux";
import "./index.css";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</StrictMode>,
rootElement
);
then App.js to render components
import "./App.css";
import { Routes, Route } from "react-router-dom";
import { SingleTodoPage } from "./Components/SingleTodoPage";
import { EditTodo } from "./Components/EditTodo";
import { Home } from "./Components/Home";
function App() {
return (
<Routes>
<div>
<div className="header-text">Todo List</div>
<div className="box">
<Route path="/" element={<Home />} />
<Route path="todo/:todoId" element={<SingleTodoPage />} />
<Route path="edit/:todoId" element={<EditTodo />} />
</div>
</div>
</Routes>
);
}
export default App;
SingleTodo where linking different components
<SingleTodo />
<List>
{todos.map((todo) => (
<ListItem key={todo.id} className={classes.listRoot}>
<ListItemText primary={todo.name} />
<ListItemSecondaryAction>
<CheckBoxIcon color="primary" />
<DeleteIcon color="secondary" />
<Link to={`edit/${todo.id}`} className="button">
<EditIcon />
</Link>
<Link to={`todo/${todo.id}`}>view</Link>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
codesandbox for more details, i am using useParams hook in SingleTodo and in EditTodo
to get dynamic url params.
please if anyone knows how to solve this please help me...thanks
Move the non-routing-related elements out of the Routes component.
function App() {
return (
<Routes>
<div>
<div className="header-text">Todo List</div>
<div className="box">
<Route path="/" element={<Home />} />
<Route path="todo/:todoId" element={<SingleTodoPage />} />
<Route path="edit/:todoId" element={<EditTodo />} />
</div>
</div>
</Routes>
);
}
To this
function App() {
return (
<div>
<div className="header-text">Todo List</div>
<div className="box">
<Routes>
<Route path="/" element={<Home />} />
<Route path="todo/:todoId" element={<SingleTodoPage />} />
<Route path="edit/:todoId" element={<EditTodo />} />
</Routes>
</div>
</div>
);
}
The Routes component functions largely as the replacement for react-router-dom v4/5's Switch component.

React-router-dom v6, URL changing but component doesn't render

I've tried everything but fail to render component when URL changes. No error messages nothing, it renders Home component but when i click on (view and edit icon)Link it just changes url, component does not render nothing happens. I couldn't find a solution, is there any way to make it work?
App.js
import "./App.css";
// import { TextFilledComp } from './Components/TextFilledComp';
import { Routes, Route } from "react-router-dom";
import { SingleTodoPage } from "./Components/SingleTodoPage";
import { EditTodo } from "./Components/EditTodo";
import { Home } from "./Components/Home";
function App() {
return (
<div>
<Routes>
<div>
<div className="header-text">Todo List</div>
<div className="box">
<Route exact path="/" element={<Home />} />
<Route path="/todo/:todoId" element={<SingleTodoPage />} />
<Route path="/edit/:TodoId" element={<EditTodo />} />
</div>
</div>
</Routes>
</div>
);
}
export default App;
Todo.js
import {
Checkbox,
List,
ListItem,
ListItemSecondaryAction,
ListItemText,
makeStyles
} from "#material-ui/core";
import DeleteIcon from "#material-ui/icons/Delete";
import EditIcon from "#material-ui/icons/Edit";
import CheckBoxIcon from "#material-ui/icons/CheckBox";
import React from "react";
import { useSelector } from "react-redux";
import { Link } from "react-router-dom";
const useStyles = makeStyles({
listRoot: {
borderWidth: "1px",
borderColor: "#aaaaaa",
borderStyle: "solid",
borderRadius: "20px"
}
});
export const TodoList = () => {
const todos = useSelector((state) => state.todo);
const classes = useStyles();
return (
<div style={{ width: "95%", margin: "10px auto" }}>
<List>
{todos.map((todo) => (
<ListItem key={todo.id} className={classes.listRoot}>
<ListItemText primary={todo.name} />
<ListItemSecondaryAction>
{/* <Checkbox
edge="end"
/> */}
<CheckBoxIcon color="primary" />
<DeleteIcon color="secondary" />
<Link to={`/edit/${todo.id}`} className="button">
<EditIcon />
</Link>
<Link to={`/todo/${todo.id}`}>view</Link>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
</div>
);
};
codesandbox link for complete app
A Routes component is the replacement for Switch from v5 and should only wrap around Route components. It's solely responsible for matching the provided paths and controlling the visibility of Routes and does not know what to do with regular JSX.
function App() {
return (
<div>
<div>
<div className="header-text">Todo List</div>
<div className="box">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/todo/:todoId" element={<SingleTodoPage />} />
<Route path="/edit/:todoId" element={<EditTodo />} />
</Routes>
</div>
</div>
</div>
);
}
I've also removed the exact prop as it is deprecated in v6 since all Routes are exact by default. To allow non-exact Routes, use the new path="/nonexact/*" syntax. Some more info on the new features can be found here.

Categories