I have a main page with a sidebar and a content displaying area which will display the selected option. The problem occurs when I try to click on the Link
in sidebar, it doesn't changes anything in the content displaying division but URL changes. If I define the routes in App.js then Link
works but it opens the component in new page, I want it to be displayed in the MainPage.js itself.
App.js:
import { useEffect, useState } from 'react';
import {
BrowserRouter as Router,
Route,
Routes,
Navigate
} from 'react-router-dom';
import LoginPage from './pages/LoginPage';
import MainPage from './pages/MainPage';
import SamplePage from './pages/SamplePage'
const App = () => {
/** HOOKS */
const [admin, setAdmin] = useState({name: "junaid"})
// const [admin, setAdmin] = useState(null)
// hook to see if admin is already logged in
useEffect(() => {
const loggedAdmin = window.localStorage.getItem('loggedProSkillzAdmin')
if (loggedAdmin) {
setAdmin(JSON.parse(loggedAdmin))
}
})
return (
<Router forcerefresh={true}>
{/* <Navigate from="/" to={admin ? "/main" : "/login"} /> */}
{/* <Navigate exact from="/" to="/main" /> */}
<Routes>
{admin === null ? (
<Route path="*" element={<LoginPage setAdmin={setAdmin} />} />
) : (
// If admin is logged in, navigate to MainPage
<>
{/* Redirect from root to /main */}
<Route path="/" element={<Navigate to="/main" />} />
<Route path="/main/*" element={<MainPage />} />
</>
)}
<Route path="*" element={<p>No Path Found</p>}/>
</Routes>
</Router>
)
}
export default App;
MainPage.js:
import { Route, Routes, Link} from 'react-router-dom';
import { MdDashboard } from "react-icons/md";
import { IoIosSettings } from "react-icons/io";
import { FaUsers, FaUserAstronaut } from "react-icons/fa";
import Sidebar from "../components/Sidebar"
import SidebarItem from "../components/SidebarItem"
import SamplePage from './SamplePage';
const MainPage = () => {
return (
<div className='flex w-full h-full'>
<Sidebar>
<SidebarItem icon={<MdDashboard/>} text="Dashboard" path="dashboard" active={true}/>
<SidebarItem icon={<FaUsers/>} text="Users" path="users" active={false}/>
<SidebarItem icon={<FaUserAstronaut/>} text="Providers" path="providers" active={false}/>
<SidebarItem icon={<IoIosSettings/>} text="Settings" path="settings" active={false}/>
</Sidebar>
<div className='w-full h-dvh bg-black'>
<Routes>
<Route path="/main/dashboard" Component={<SamplePage title={"Dashboard"} index/>}/>
<Route path="/main/users" element={<SamplePage title={"Users"}/>}/>
<Route path="/main/providers" element={<SamplePage title={"Providers"}/>}/>
<Route path="/main/settings" element={<SamplePage title={"Settings"}/>}/>
</Routes>
</div>
</div>
)
}
export default MainPage
SidebarItem.js:
import { useContext } from "react"
import { SidebarContext } from "./Sidebar";
import { IoSettings } from "react-icons/io5";
import { Link } from "react-router-dom";
const SidebarItem = ({ icon, text, path, active }) => {
const { expanded } = useContext(SidebarContext)
return (
<>
<Link
to={`/main/${path}`}
className={`
relative flex items-center py-2 px-3 my-1
font-medium rounded-md cursor-pointer
${active
? "bg-indigo-800 text-white"
: "hover:text-white hover:bg-indigo-800 "
}
`}
>
<div>{icon}</div>
<span className={`
overflow-hidden transition-all
${expanded? "w-52 ml-3 visible":"w-0 invisible"}
`}>
{text}
</span>
</Link>
</>
)
}
export default SidebarItem
SamplePage.js:
const SamplePage = ({ title }) => {
console.log('Sample page works for ', title)
return (
<div className="bg-red-700 w-full h-full">
{title}
</div>
)
}
export default SamplePage
After clicking the Link(notice url changes)
Expecting somehow the component renders in the MainPage.js
Descendent routes build relative to the parent route. MainPage
is rendered on path "/main/*"
:
<Route path="/main/*" element={<MainPage />} />
But is including another "main"
path segment in its descendent routes:
<Routes>
<Route
path="/main/dashboard"
Component={<SamplePage title="Dashboard" index />}
/>
<Route path="/main/users" element={<SamplePage title="Users" />} />
<Route path="/main/providers" element={<SamplePage title="Providers" />} />
<Route path="/main/settings" element={<SamplePage title="Settings" />} />
</Routes>
This means the URL path is actually "/main/main/dashboard"
, etc.
Remove the extraneous "main"
path segment from the descendent routes. Be sure to correctly use the element
prop instead of Component
since you are not using a Data router.
<Routes>
<Route path="/dashboard" element={<SamplePage title="Dashboard" />} />
<Route path="/users" element={<SamplePage title="Users" />} />
<Route path="/providers" element={<SamplePage title="Providers" />} />
<Route path="/settings" element={<SamplePage title="Settings" />} />
</Routes>