I am having problems displaying a child component.
App.js
<Route
element={<ProtectedRoutes allowedRoles={[userRoles.FIELD_FORCE_MANAGER]} />}
>
<Route
path="/dashboard-ff"
element={
<DashboardWrapper>
<FieldForceDashboard />
</DashboardWrapper>
}
/>
</Route>
Right now I have the allowed userRole. So my <ProtectedRoutes>
has no issue. But anyway that is the code:
import React from "react";
import { Navigate, Outlet } from "react-router-dom";
import { useSelector } from "react-redux";
import PropTypes from "prop-types";
const ProtectedRoutes = ({ allowedRoles }) => {
const { isAuthenticated, userRole } = useSelector((state) => state.auth);
return isAuthenticated && allowedRoles.includes(userRole)
? <Outlet />
: <Navigate to="/" />;
};
ProtectedRoutes.propTypes = {
allowedRoles: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default ProtectedRoutes;
DashboardWrapper:
return (
<>
<Sidenav
color={sidenavColor}
brand={(transparentSidenav && !darkMode) || whiteSidenav
? brandDark
: brandWhite
}
brandName="Pharm"
routes={routes}
onMouseEnter={handleOnMouseEnter}
onMouseLeave={handleOnMouseLeave}
/>
<Outlet />
</>
);
Note my DashboardWrapper
is being rendered. The problem is with rendering FieldForceDashboard
. Note that FieldForceDashboard
is being rendered if I remove DashboardWrapper
in App.js as follows:
<Route
element={<ProtectedRoutes allowedRoles={[userRoles.FIELD_FORCE_MANAGER]} />}
>
<Route
path="/dashboard-ff"
element={<FieldForceDashboard />}
/>
</Route>
If FieldForceDashboard
is rendered when not directly wrapped by the DashboardWrapper
then the issue is just that DashboardWrapper
isn't rendering its children
prop.
DashboardWrapper
is a wrapper component so it should render the children
prop. Outlet
components are used by layout route components to allow nested routes to render their element
content.
Update DashboardWrapper
to render children
instead of Outlet
.
const DashboardWrapper = ({ children }) => {
...
return (
<>
<Sidenav
color={sidenavColor}
brand={(transparentSidenav && !darkMode) || whiteSidenav ? brandDark : brandWhite}
brandName="Pharm"
routes={routes}
onMouseEnter={handleOnMouseEnter}
onMouseLeave={handleOnMouseLeave}
/>
{children}
</>
);
};
<Route
element={(
<ProtectedRoutes
allowedRoles={[userRoles.FIELD_FORCE_MANAGER]}
/>
)}
>
<Route
path="/dashboard-ff"
element={(
<DashboardWrapper> // <-- renders children
<FieldForceDashboard /> // <-- child
</DashboardWrapper>
)}
/>
</Route>
If you wish for DashboardWrapper
to be a layout route then I suggest renaming it to DashboardLayout
and render it as a layout route.
Example:
const DashboardLayout = () => {
...
return (
<>
<Sidenav
color={sidenavColor}
brand={(transparentSidenav && !darkMode) || whiteSidenav ? brandDark : brandWhite}
brandName="Pharm"
routes={routes}
onMouseEnter={handleOnMouseEnter}
onMouseLeave={handleOnMouseLeave}
/>
<Outlet />
</>
);
};
<Route
element={(
<ProtectedRoutes
allowedRoles={[userRoles.FIELD_FORCE_MANAGER]}
/>
)}
>
<Route element={<DashboardLayout />}>
<Route path="/dashboard-ff" element={<FieldForceDashboard />} />
</Route>
</Route>