My sidebar uses react-router-dom to switch between page files using routes, however when I switch routes, my page reloads. Is there a way I can switch routes without reloading the page?
SideBar
import React from 'react'
import {SideNav_Data} from "./SideNav_Data"
import Sunrise from './Sunrise.png'
function SideNav() {
return (
<div className = "SideNav">
<img src={Sunrise} className='SideNavImg' alt=''/>
<ul className="SideNavList">
{SideNav_Data.map((val, key) => {
return (
<li key={key}
className = "row"
id={window.location.pathname === val.link ? "active" : ""}
onClick = {() => {
window.location.pathname = val.link;
}}>
<div id='icon'>{val.icon}</div>{" "}<div id='title'>{val.title}</div>
</li>
)
})}
</ul>
</div>
)
}
export default SideNav
Sidebar Data
import React from 'react'
import CottageIcon from '@mui/icons-material/Cottage';
import DirectionsCarFilledIcon from '@mui/icons-material/DirectionsCarFilled';
import PersonIcon from '@mui/icons-material/Person';
import AccountBalanceIcon from '@mui/icons-material/AccountBalance';
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
import ContactSupportIcon from '@mui/icons-material/ContactSupport';
export const SideNav_Data = [
{
title: "Home",
icon: <CottageIcon />,
link: "/"
},
{
title: "Cars",
icon: <DirectionsCarFilledIcon />,
link: "/Cars"
},
{
title: "Representatives",
icon: <PersonIcon />,
link: "/Representatives"
},
{
title: "Loan Estimator",
icon: <AccountBalanceIcon />,
link: "/Loan-Estimator"
},
{
title: "Account",
icon: <AccountCircleIcon />,
link: "/Account"
},
{
title: "Support",
icon: <ContactSupportIcon />,
link: "/Support"
},
]
Home page
import React from 'react'
import SideNav from '../Components/SideNav'
function Home() {
return (<div>
<SideNav />
</div>
)
}
export default Home
App.js
import './App.css';
import { BrowserRouter as Router, Routes, Route} from "react-router-dom"
import Home from './Pages/Home';
import Cars from './Pages/Cars';
import Reps from './Pages/Reps';
import LoanEst from './Pages/LoanEst';
import Account from './Pages/Account';
import Support from './Pages/Support';
function App() {
return (
<Router>
<Routes>
<Route path='/' element={<Home />}/>
<Route path="/Cars" element={<Cars />}/>
<Route path="/Representatives" element={<Reps />}/>
<Route path="/Loan-Estimator" element={<LoanEst />}/>
<Route path="/Account" element={<Account />}/>
<Route path="/Support" element={<Support />}/>
</Routes>
</Router>
)
}
export default App;
I've tried switching the "link: " part of the sidebar data to <Link to={Home /}/> but that resulted in the sidebar completely disappearing.
CodePudding user response:
You should use the Link component instead of changing window.location.pathname:
{SideNav_Data.map((val, key) => {
return (
<Link
key={key}
className = "row"
id={window.location.pathname === val.link ? "active" : ""}
to={val.link}
>
<div id='icon'>{val.icon}</div>{" "}<div id='title'>{val.title}</div>
</Link>
)
})}
CodePudding user response:
Issues
Using
window.location.pathnameto set the current URL path will necessarily trigger a page reload and remount the entire app. Use one of the link components exported fromreact-router-domto issue declarative navigation actions within the app.The
SideNavcomponent disappears because it is only rendered when theHomecomponent is rendered when the path is"/". Use a layout route to render theSideNavcomponent
Solution
I suggest importing and using the NavLink component as it's a special version of the Link component that applies an "active" classname by default. If you need to compute the id attribute for the li element then use the useLocation hook to access the current location.pathname value.
Example:
import { NavLink, useLocation } from 'react-router-dom';
...
function SideNav() {
const { pathname } = useLocation();
return (
<div className="SideNav">
<img src={Sunrise} className='SideNavImg' alt='' />
<ul className="SideNavList">
{SideNav_Data.map((val) => (
<li
key={val.link}
className="row"
id={pathname === val.link ? "active" : ""}
>
<NavLink to={val.link} end>
<div id='icon'>{val.icon}</div>
{" "}
<div id='title'>{val.title}</div>
</NavLink>
</li>
))}
</ul>
</div>
);
}
Render the SideNav as part of a layout route so it's conditionally rendered with the routes you want it to be rendered with.
Example:
import {
BrowserRouter as Router,
Routes,
Route,
Outlet,
} from "react-router-dom"
import Home from './Pages/Home';
import Cars from './Pages/Cars';
import Reps from './Pages/Reps';
import LoanEst from './Pages/LoanEst';
import Account from './Pages/Account';
import Support from './Pages/Support';
import SideNav from './Components/SideNav';
const SideNavLayout = () => (
<>
<SideNav />
<Outlet />
</>
);
function App() {
return (
<Router>
<Routes>
<Route element={<SidNavLayout />}>
<Route path='/' element={<Home />} />
<Route path="/Cars" element={<Cars />} />
<Route path="/Representatives" element={<Reps />} />
<Route path="/Loan-Estimator" element={<LoanEst />} />
<Route path="/Account" element={<Account />} />
<Route path="/Support" element={<Support />} />
</Route>
</Routes>
</Router>
);
}
Home
import React from 'react';
function Home() {
return (
<div>
...
</div>
);
}
export default Home;
