skip to Main Content

Router does not render component. At home page Prive route is rendered once. When I click NavLink browser change url i.e. "/agreements" but component is not rendered. I run out of ideas.

AppRoutes.tsx

const PrivateRoute = ({ children }: { children?: any }) => {
  return <AuthorizedLayout>{children}</AuthorizedLayout>;
};

const router = createBrowserRouter(
  createRoutesFromElements(
    <React.Fragment>
      <Route path={routes.home.path} element={<PrivateRoute />}>
        <Route
          index
          path={routes.agreements.path}
          element={
            <PrivateRoute>
              <AgreementsView />
            </PrivateRoute>
          }
        ></Route>
        <Route
          path={routes.send.path}
          element={
            <PrivateRoute>
              <SendView />
            </PrivateRoute>
          }
        ></Route>
        <Route
          index
          path={routes.settings.path}
          element={
            <PrivateRoute>
              <SettingsView />
            </PrivateRoute>
          }
        ></Route>
      </Route>

      <Route
        path={routes.login.path}
        element={
          <UnauthorizedLayout>
            <LoginComponent />
          </UnauthorizedLayout>
        }
      ></Route>
    </React.Fragment>
  )
);

const AppRoutes = () => {
  return <RouterProvider router={router} />;
};

App.tsx In root I use AppRoutes. I can move RouterProvider higher. Wrap ThemeProvider. It does not matter. The result is the same.

import AppRoutes from "./routes.component";
import { ThemeProvider } from "./shared/theme";

function App() {
  return (
    <ThemeProvider>
      <AppRoutes />
    </ThemeProvider>
  );
}

export default App;

menu.component.tsx

import {
  NavLink as NavLinkBase,
  useMatch,
  useResolvedPath,
} from "react-router-dom";
import { routes } from "../../../shared/utils/routes";
import {
  List,
  ListItem,
  ListItemButton,
  ListItemIcon,
  ListItemText,
} from "@mui/material";
import AssignmentIcon from "@mui/icons-material/Assignment";
import OutboxIcon from "@mui/icons-material/Outbox";
import React from "react";
import SettingsApplicationsIcon from "@mui/icons-material/SettingsApplications";
import customTheme from "../../../shared/theme/custom-theme";

export const links = [
  {
    id: "agreements",
    to: routes.agreements.path,
    icon: <AssignmentIcon />,
    translationKey: "Umowy",
  },
  {
    id: "send",
    to: routes.send.path,
    icon: <OutboxIcon />,
    translationKey: "Wysyłka",
  },
  {
    id: "settings",
    to: routes.settings.path,
    icon: <SettingsApplicationsIcon />,
    translationKey: "Ustawienia",
  },
];

const NavLink = React.forwardRef((props, ref) => {
  const resolved = useResolvedPath(props.to);
  const match = useMatch({ path: resolved.pathname, end: true });

  return (
    <NavLinkBase
      ref={ref}
      {...props}
      style={{
        backgroundColor: match ? customTheme.palette.primary.dark : "",
      }}
    />
  );
});

export const MenuItems = ({ onClick }: { onClick: any }) => {
  return (
    <>
      {links.map((link) => (
        <ListItem
          key={link.translationKey}
          as={NavLink}
          to={link.to}
          onClick={onClick}
          disablePadding
        >
          <ListItemButton>
            <ListItemIcon>{link.icon}</ListItemIcon>
            <ListItemText primary={link.translationKey} />
          </ListItemButton>
        </ListItem>
      ))}
    </>
  );
};

const Menu = () => {
  return (
    <List>
      <MenuItems onClick={() => {}}></MenuItems>
    </List>
  );
};

export default Menu;
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^6.17.0",
"react-router-dom": "^6.17.0",

3

Answers


  1. Chosen as BEST ANSWER

    Remove nested "/home" route solve the issue. this should be removed
    <Route path={routes.home.path} element={<PrivateRoute />}> </Route>


  2. Did you try to use useNavigate from react-router-dom v6?

    const navigate = useNavigate();
    navigate(`path here`)
    
    Login or Signup to reply.
  3. The "agreements" route and component is currently nested under the "home" route, e.g. its route path may resolve to something more like "/home/agreements". If the intention is for "/agreements" to be a root route then the solution is to unnest the routes from path={routes.home.path}.

    You could also make the code more DRY by converting PrivateRoute from a wrapper component into a layout route component, e.g. it renders an Outlet component instead of a children prop, and is rendered as a parent route instead of directly wrapping routed content.

    See Layout Routes and Outlets for more details.

    Example:

    import { Outlet } from 'react-router-dom';
    
    const PrivateRoute = () => {
      return (
        <AuthorizedLayout>
          <Outlet />
        </AuthorizedLayout>
      );
    };
    
    const router = createBrowserRouter(
      createRoutesFromElements(
        <React.Fragment>
          <Route element={<PrivateRoute />}>
            <Route path={routes.agreements.path} element={<AgreementsView />} />
            <Route path={routes.send.path} element={<SendView />} />
            <Route path={routes.settings.path} element={<SettingsView />} />
          </Route>
    
          <Route
            path={routes.login.path}
            element={
              <UnauthorizedLayout>
                <LoginComponent />
              </UnauthorizedLayout>
            }
          />
        </React.Fragment>
      )
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search