Home > database >  How to prevent page reoading after switching routes
How to prevent page reoading after switching routes

Time:11-03

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.pathname to set the current URL path will necessarily trigger a page reload and remount the entire app. Use one of the link components exported from react-router-dom to issue declarative navigation actions within the app.

  • The SideNav component disappears because it is only rendered when the Home component is rendered when the path is "/". Use a layout route to render the SideNav component

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;
  • Related