skip to Main Content

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.

2

Answers


  1. Outlet should be used in parent route elements to render their child route elements and I don’t recommend conditionally render the route component

    import CoursesAdmin from './components/administrator/CoursesAdmin'
    import Main from './components/..';//somewhere
    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={<Main/>}>
              <Route path="login" element={<Login />} />
            </Route>
            :
            <Route path="/" element={<Main/>}>
              <Route path="/home" element={<Home />} />
              <Route index element={<ProtectedRoute/>}>
              <Route path="courses" element={<CoursesAdmin/>} />
            </Route>
        )
      );
    
    
      return (
        <RouterProvider router={routes} />
      )
    
    Login or Signup to reply.
  2. 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>
          </>
        );
      };
      

    Edit why-react-router-dom-outlet-does-not-display-the-component

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search