I have a component that holds the four different components
const ProtectedRoute = () => {
return (
<>
<Header />
<div className='flex h-screen overflow-hidden'>
<div className="md:block hidden fixed top-[25%] ml-2 opacity-80 hover:opacity-100">
<AdminLinks />
</div>
<div className="w-3/4 overflow-auto">
<div className='h-full p-4'>
<Main/>
</div>
</div>
<div className='w-1/4 overflow-auto'>
<Status/>
</div>
</div>
</>
)
}
Header (which does not have a navigation links only in mobile)
UserLinks (inside of this it uses the reusable side navigation component)
const AdminLinks = (props) => {
return (
<>
{userLinks.map((nav) => (
<SideNav
key={nav.id}
id={nav.id}
link={nav.link}
icon={nav.icon}
title={nav.title}
classname={props.classname}
/>
))}
</>
)
}
Main (in this component it should display the children component I specified in the route)
const Main = () => {
return (
<div className="w-full flex flex-col justify-start ml-4 px-4">
<Outlet />
</div>
)
}
and Status.
In the App component
import CoursesAdmin from './components/administrator/CoursesAdmin'
function App() {
// eslint-disable-next-line no-unused-vars
const [isLog, setisLog] = useState(false);
const routes = createBrowserRouter(
createRoutesFromElements(
// Displayed when user is not authenticated
isLog ?
<Route path="/" element={<Login />}>
<Route path="login" element={<Login />} />
</Route>
:
<Route path="/" element={<ProtectedRoute />}>
<Route index element={<Home />} />
<Route path="courses" element={<CoursesAdmin />} />
</Route>
)
);
return (
<RouterProvider router={routes} />
)
I initialized the createBrowserRouter
and created a routes
element. The problem is when I click the side navigation it does not display the component inside of the Main rather it throws a "page not found" error.
When I clicked the specific nav of side navigation it should render the path and element provided to it in the inside of the Main
component.
There is no issue with where you are rendering the Outlet
, but you do have some anti-patterns in your implementation.
You should not conditionally render routes. Render all routes and use a proper route guard to protect specific routes.
Pass the setIsLog
state updater to the Login
component so it can update the local isLog
state when a user logs in.
Pass isLog
to ProtectedRoute
so it can handle protecting its sub-routes.
export default function App() {
const [isLog, setIsLog] = useState(false);
const router = createBrowserRouter(
createRoutesFromElements(
// Displayed when user is not authenticated
<Route path="/">
<Route path="login" element={<Login setIsLog={setIsLog} />} />
<Route element={<ProtectedRoute isLog={isLog} />}>
<Route index element={<Home />} />
<Route path="courses" element={<CoursesAdmin />} />
</Route>
</Route>
)
);
return <RouterProvider router={router} />;
}
Update ProtectedRoute
to consume the passed isLog
prop and redirect to "/login"
if user is unauthenticated.
const ProtectedRoute = ({ isLog }) => {
if (!isLog) return <Navigate to="/login" replace />;
return (
<>
<Header />
<div className="flex h-screen overflow-hidden">
<div className="md:block hidden fixed top-[25%] ml-2 opacity-80 hover:opacity-100">
<AdminLinks />
</div>
<div className="w-3/4 overflow-auto">
<div className="h-full p-4">
<Main />
</div>
</div>
<div className="w-1/4 overflow-auto">
<Status />
</div>
</div>
</>
);
};