-
-
Notifications
You must be signed in to change notification settings - Fork 411
Description
Steps to reproduce
RouteManager.jsx
import { ThemeContext } from "@emotion/react";
import CircularProgress from "@mui/material/CircularProgress";
import { UserContext } from "context/UserContext";
import Offline from "pages/public/Offline";
import { lazy, Suspense, useContext } from "react";
import { Route, Routes } from "react-router-dom";
import { ToastContainer } from "react-toastify";
const Private = lazy(() => import("./Private"));
const Public = lazy(() => import("./Public"));
export default function RouteManager() {
const userCntx = useContext(UserContext);
const themeContext = useContext(ThemeContext);
return (
<>
<Suspense fallback={<CircularProgress sx={{ mx: "auto", my: "50%" }} />}>
<Routes>
{
userCntx.isAuthenticated ? <Route path="/dashboard/*" element={<Private />} /> : null
}
<Route path="/offline/" element={<Offline />} />
<Route index path="/*" element={<Public />} />
</Routes >
<ToastContainer
autoClose={5000}
rtl={true}
pauseOnFocusLoss
draggable
pauseOnHover
theme={themeContext.isDarkMode ? "dark" : "light"}
/>
</Suspense>
</>
);
}
Private.jsx
import { Alert, Box, CircularProgress, useTheme } from '@mui/material';
import { PageContainer } from '@toolpad/core';
import { DashboardLayout } from '@toolpad/core/DashboardLayout';
import { ReactRouterAppProvider } from "@toolpad/core/react-router";
import urls from 'api/urls';
import logo from "assets/images/logo.png";
import useGetObj from "hooks/useGetObj";
import { lazy, useEffect, useState } from "react";
import { Route, Routes } from 'react-router-dom';
import get_pages from "utils/get_pages";
const Dashboard = lazy(() => import("pages/private/dashboard/MainDashboard"));
const Profile = lazy(() => import("pages/private/profile/Profile"));
const AddArticle = lazy(() => import("pages/private/Articles/AddArticle"));
const ArticleList = lazy(() => import("pages/private/Articles/ArticleList"));
const Users = lazy(() => import("pages/private/users/Users"));
const branding = {
homeUrl: "/",
logo: <img src={logo} alt="Logo" />,
title: "Website"
};
export default function Private() {
const theme = useTheme();
const [navigation, setNavigation] = useState([]);
const [user, isLoaded, error] = useGetObj({ url: `${urls.account}profile/` });
useEffect(() => {
if (isLoaded && !error && user) {
const pages = get_pages(user);
setNavigation(pages);
}
}, [user, isLoaded, error]);
if (!isLoaded) {
return <Box sx={{ mt: 20, textAlign: 'center' }}><CircularProgress /></Box>;
} else if ((isLoaded && user === null) || error) {
return (
<Box sx={{ mt: 20, textAlign: 'center', p: 5 }}>
<Alert severity='error'>
Error
</Alert>
</Box>
);
}
else if (isLoaded && !user.is_active) {
return (
<Box sx={{ mt: 20, textAlign: 'center', p: 5 }}>
<CircularProgress />
</Box>
);
} else {
return (
<ReactRouterAppProvider theme={theme} branding={branding} navigation={navigation} session={user} >
<DashboardLayout>
<PageContainer>
<Routes>
<Route path="/" exact index element={<Dashboard />} />
<Route path='profile/' element={<Profile />} />
{
user.is_superuser ?
<>
<Route path='article/' element={<AddArticle />} />
<Route path='article/add/' element={<AddArticle />} />
<Route path='article/list/' element={<ArticleList />} />
<Route path='users/' element={<Users />} />
</> : null
}
</Routes>
</PageContainer>
</DashboardLayout>
</ReactRouterAppProvider>
);
}
}getPages.js
import CreateRoundedIcon from '@mui/icons-material/CreateRounded';
import DashboardIcon from '@mui/icons-material/Dashboard';
import NewspaperRoundedIcon from '@mui/icons-material/NewspaperRounded';
import PersonRoundedIcon from '@mui/icons-material/PersonRounded';
import SegmentRoundedIcon from '@mui/icons-material/SegmentRounded';
const Base_NAVIGATION = [
{
kind: 'header',
title: 'User Dashboard',
},
{
segment: 'dashboard',
pattern: 'dashboard(/)?',
title: 'Dashboard',
icon: <DashboardIcon />,
},
{
segment: 'dashboard/profile',
pattern: 'dashboard/profile(/)?',
title: 'Profile',
icon: <PersonRoundedIcon />,
},
];
export default function get_pages(user) {
const pages = Base_NAVIGATION;
if (user.is_superuser) {
pages.push(
{
kind: 'header',
title: 'Auther Dashboard',
},
{
segment: 'dashboard/article',
pattern: 'dashboard/article(/)?',
title: 'Articles',
icon: <NewspaperRoundedIcon />,
children: [
{
segment: 'add',
pattern: 'dashboard/article/add(/)?', // Add full pattern
title: 'Add',
icon: <CreateRoundedIcon />
},
{
segment: 'list',
pattern: 'dashboard/article/list(/)?', // Add full pattern
title: 'List',
icon: <SegmentRoundedIcon />
},
]
},
);
return pages;
}
return pages;
}Note: Just use dummy component for Route elements. It doesn't matter because they are empty screens like
function Untitled() {
return (
<div>Untitled</div>
)
}
export default Untitled;Current behavior
Page doesn't shows up and says
Item not found in navigation: Add
invariant@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7730:15
getItemPath@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7028:41
./node_modules/@toolpad/core/esm/shared/navigation.js/hasSelectedNavigationChildren/<@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7044:33
hasSelectedNavigationChildren@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7037:26
./node_modules/@toolpad/core/esm/DashboardLayout/DashboardSidebarSubNavigation.js/DashboardSidebarSubNavigation/initialExpandedItemIds</<@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:5732:194
./node_modules/@toolpad/core/esm/DashboardLayout/DashboardSidebarSubNavigation.js/DashboardSidebarSubNavigation/initialExpandedItemIds<@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:5730:7
mountMemo@http://localhost:3000/static/js/bundle.js:46922:21
useMemo@http://localhost:3000/static/js/bundle.js:55131:16
./node_modules/react/cjs/react.development.js/exports.useMemo@http://localhost:3000/static/js/bundle.js:70415:32
DashboardSidebarSubNavigation@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:5727:69
react_stack_bottom_frame@http://localhost:3000/static/js/bundle.js:56014:18
renderWithHooks@http://localhost:3000/static/js/bundle.js:46224:38
updateFunctionComponent@http://localhost:3000/static/js/bundle.js:47917:17
beginWork@http://localhost:3000/static/js/bundle.js:48503:16
runWithFiberInDEV@http://localhost:3000/static/js/bundle.js:43995:125
performUnitOfWork@http://localhost:3000/static/js/bundle.js:50576:93
workLoopSync@http://localhost:3000/static/js/bundle.js:50469:55
renderRootSync@http://localhost:3000/static/js/bundle.js:50453:7
performWorkOnRoot@http://localhost:3000/static/js/bundle.js:50217:42
performSyncWorkOnRoot@http://localhost:3000/static/js/bundle.js:51181:22
flushSyncWorkAcrossRoots_impl@http://localhost:3000/static/js/bundle.js:51100:306
flushSpawnedWork@http://localhost:3000/static/js/bundle.js:50878:36
commitRoot@http://localhost:3000/static/js/bundle.js:50722:7
commitRootWhenReady@http://localhost:3000/static/js/bundle.js:50287:15
Also console log is
Uncaught Invariant Violation: Item not found in navigation: Add
invariant http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7730
getItemPath http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7028
node_modules toolpad/core/esm/shared/navigation.js/hasSelectedNavigationChildren/<@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7044
hasSelectedNavigationChildren http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7037
node_modules toolpad/core/esm/DashboardLayout/DashboardSidebarSubNavigation.js/DashboardSidebarSubNavigation/initialExpandedItemIds</<@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:5732
node_modules toolpad/core/esm/DashboardLayout/DashboardSidebarSubNavigation.js/DashboardSidebarSubNavigation/initialExpandedItemIds<@http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:5730
mountMemo http://localhost:3000/static/js/bundle.js:46922
useMemo http://localhost:3000/static/js/bundle.js:55131
useMemo http://localhost:3000/static/js/bundle.js:70415
DashboardSidebarSubNavigation http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:5727
react_stack_bottom_frame http://localhost:3000/static/js/bundle.js:56014
renderWithHooks http://localhost:3000/static/js/bundle.js:46224
updateFunctionComponent http://localhost:3000/static/js/bundle.js:47917
beginWork http://localhost:3000/static/js/bundle.js:48503
runWithFiberInDEV http://localhost:3000/static/js/bundle.js:43995
performUnitOfWork http://localhost:3000/static/js/bundle.js:50576
workLoopSync http://localhost:3000/static/js/bundle.js:50469
renderRootSync http://localhost:3000/static/js/bundle.js:50453
performWorkOnRoot http://localhost:3000/static/js/bundle.js:50217
performSyncWorkOnRoot http://localhost:3000/static/js/bundle.js:51181
flushSyncWorkAcrossRoots_impl http://localhost:3000/static/js/bundle.js:51100
flushSpawnedWork http://localhost:3000/static/js/bundle.js:50878
commitRoot http://localhost:3000/static/js/bundle.js:50722
commitRootWhenReady http://localhost:3000/static/js/bundle.js:50287
setTimeout handler*performWorkOnRoot http://localhost:3000/static/js/bundle.js:50264
performWorkOnRootViaSchedulerTask http://localhost:3000/static/js/bundle.js:51173
performWorkUntilDeadline http://localhost:3000/static/js/bundle.js:70529
js http://localhost:3000/static/js/bundle.js:70648
js http://localhost:3000/static/js/bundle.js:70755
factory http://localhost:3000/static/js/bundle.js:77884
__webpack_require__ http://localhost:3000/static/js/bundle.js:77239
fn http://localhost:3000/static/js/bundle.js:77500
hotRequire http://localhost:3000/static/js/bundle.js:77867
js http://localhost:3000/static/js/bundle.js:70770
factory http://localhost:3000/static/js/bundle.js:77884
__webpack_require__ http://localhost:3000/static/js/bundle.js:77239
fn http://localhost:3000/static/js/bundle.js:77500
hotRequire http://localhost:3000/static/js/bundle.js:77867
js http://localhost:3000/static/js/bundle.js:53775
js http://localhost:3000/static/js/bundle.js:56776
factory http://localhost:3000/static/js/bundle.js:77884
__webpack_require__ http://localhost:3000/static/js/bundle.js:77239
fn http://localhost:3000/static/js/bundle.js:77500
hotRequire http://localhost:3000/static/js/bundle.js:77867
js http://localhost:3000/static/js/bundle.js:57000
factory http://localhost:3000/static/js/bundle.js:77884
__webpack_require__ http://localhost:3000/static/js/bundle.js:77239
fn http://localhost:3000/static/js/bundle.js:77500
hotRequire http://localhost:3000/static/js/bundle.js:77867
js http://localhost:3000/static/js/bundle.js:76668
factory http://localhost:3000/static/js/bundle.js:77884
__webpack_require__ http://localhost:3000/static/js/bundle.js:77239
<anonymous> http://localhost:3000/static/js/bundle.js:78488
<anonymous> http://localhost:3000/static/js/bundle.js:78490
[vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js:7730:15](http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_esm_CreateRounded_js-node_modules_mui_icons-material_-797098.chunk.js)
An error occurred in the <DashboardSidebarSubNavigation> component.
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://react.dev/link/error-boundaries to learn more about error boundaries.
Expected behavior
Show pages under /dashboard/ path instead of root or anything else without any error.
Context
I have 2 routes.
- Public
- Private
Public URLs are under root (/) and private URL which needs authentication and are under dashboard (/dashboard).
get_pages is responsible for getting dashboard pages according user accesses and permissions.
RouteManager is responsible for checking for users authentication and let them to access private pages
I tried many approaches to put side navigation's in dashboard under /dashboard/ in this scenario but either they went under root url (when I change url/pattern in get_pages) or just not shows up when I put location prop to Routes in Private.jsx.
Your environment
Firefox
npx @mui/envinfo
System:
OS: Linux 6.14 Ubuntu 24.04.3 LTS 24.04.3 LTS (Noble Numbat)
Binaries:
Node: 22.13.0 - ~/.nvm/versions/node/v22.13.0/bin/node
npm: 10.9.2 - ~/.nvm/versions/node/v22.13.0/bin/npm
pnpm: Not Found
Browsers:
Chrome: Not Found
npmPackages:
@emotion/react: ^11.14.0 => 11.14.0
@emotion/styled: ^11.14.1 => 11.14.1
@mui/core-downloads-tracker: 7.3.1
@mui/icons-material: 7.3.1 => 7.3.1
@mui/material: 7.3.1 => 7.3.1
@mui/private-theming: 7.3.1
@mui/styled-engine: 7.3.1
@mui/styled-engine-sc: 7.3.1 => 7.3.1
@mui/system: 7.3.1
@mui/types: 7.4.5
@mui/utils: 7.3.1
@mui/x-data-grid: 8.10.1
@mui/x-date-pickers: ^8.10.0 => 8.10.0
@mui/x-internals: 8.10.0
@mui/x-virtualizer: 0.1.2
@toolpad/core: ^0.16.0 => 0.16.0
@toolpad/utils: 0.16.0
react: ^19.1.1 => 19.1.1
react-dom: ^19.1.1 => 19.1.1
styled-components: ^6.1.19 => 6.1.19
typescript: ^5.9.2 => 5.9.2
Search keywords: navigation, react
Metadata
Metadata
Assignees
Labels
Projects
Status