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
Remove nested "/home" route solve the issue. this should be removed
<Route path={routes.home.path} element={<PrivateRoute />}> </Route>
Did you try to use
useNavigate
from react-router-dom v6?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 frompath={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 anOutlet
component instead of achildren
prop, and is rendered as a parent route instead of directly wrapping routed content.See Layout Routes and Outlets for more details.
Example: