How to map Routes from array? - reactjs

I Have some routes:
export const publicRoutes = [
{
path: MAIN_ROUTE,
Component: Main
},
{
path: ABOUT_ROUTE,
Component: About
}
]
And I want to create some Routes into BrowserRouter:
<BrowserRouter>
<Routes>
{publicRoutes.map(({path, Component}) => (
<Route key={path} path={path} element={Component}/> // Type '() => JSX.Element' is not assignable to type 'ReactNode'.
))}
</Routes>
</BrowserRouter>
TypeScript throws an error Type '() => JSX.Element' is not assignable to type 'ReactNode'.

You have to define the routes array items as jsx intially
export const publicRoutes = [
{
path: MAIN_ROUTE,
Component: <Main/>
},
{
path: ABOUT_ROUTE,
Component: <About/>
}
]
You can also use useRoutes to make things even more elegant (https://reactrouter.com/docs/en/v6/hooks/use-routes#useroutes)
Example from Docs:
import * as React from "react";
import { useRoutes } from "react-router-dom";
function App() {
let element = useRoutes([
{
path: "/",
element: <Dashboard />,
children: [
{
path: "messages",
element: <DashboardMessages />,
},
{ path: "tasks", element: <DashboardTasks /> },
],
},
{ path: "team", element: <AboutPage /> },
]);
return element;
}

Related

Nested Protected routes and react-router race condition

I am on react-router v6. I have an app that I've created Protected routes for and so far it works. However I have requirements to protect a few routes that are nested (within a protected route) which is where bugs are occurring.
My attempt to explain:
I have a hook that will fetch necessary member information at the top most level. This is used in tandem with useReactiveVar w/ apollo and a graphql backend. This works for the most part.
While this fetches, I have one level of protected routing -- this will check if the user is logged in via `localStorage.getItem('access_token').
In my second level of protected routing, it'll try to read data from the aforementioned member information. This will be undefined while the information is being fetched.
The first level of protected routing is resolved. My second level of protection is then ignored since member data is null. I think this is a race condition?
My code:
// ProtectedRoute.tsx
export const ProtectedRoute = ({
redirectPath = Routes.Landing,
isAllowed,
noBaseLayout,
}: ProtectedRouteProps) => {
if (!isAllowed) {
return <Navigate to={redirectPath} replace />;
}
if (noBaseLayout) {
return <Outlet />;
}
return (
<BaseLayout>
<Outlet />
</BaseLayout>
);
};
export default function routes() {
const isLoggedIn = localStorage.getItem('access_token');
const currentUser = useReactiveVar(currentMeVar); // This will be null at first until it resolves
const elements: RouteObject[] = [
// Unauth'd routes. Visiting these routes *with* a user will direct back to the dashboard
{
element: (
<ProtectedRoute isAllowed={!isLoggedIn} redirectPath={Routes.Dashboard} noBaseLayout />
),
children: [
{
path: Routes.Landing,
element: <LandingPage />,
},
{
path: Routes.PatientLoginToken,
element: <LoginTokenPage scope={UserScope.Member} />,
},
{
path: Routes.CaregiverLoginToken,
element: <LoginTokenPage scope={UserScope.Caregiver} />,
},
{
path: Routes.PatientLogin,
element: <PatientLoginPage />,
},
{
path: Routes.RequestLoginEmail,
element: <RequestEmailLoginPage />,
},
{ path: Routes.CaregiverLogin, element: <CaregiverLoginPage /> },
{ path: Routes.CaregiverCompleteSignup, element: <CaregiverCompleteSignupPage /> },
{
path: Routes.PatientSignup,
element: <PatientSignupPageOneStep />,
},
{
path: Routes.PatientSignupClient,
element: <PatientSignupPageOneStep />,
},
],
},
// Auth'd routes. Visiting these routes *without* a user will redirect back to the landing page
{
element: <ProtectedRoute isAllowed={!!isLoggedIn} />,
children: [
{ path: Routes.Dashboard, element: <DashboardPage /> },
{ path: Routes.ContentLibrary, element: <ContentLibraryBrowsePage /> },
// Auth'd, but user has no covered life yet. This will redirect back to the dashboard page
{
element: (
<ProtectedRoute
isAllowed={currentUser?.member.hasCoveredLifeAttached}
redirectPath={Routes.Dashboard}
noBaseLayout
/>
),
children: [
{ path: Routes.Scheduling, element: <ScheduleSessionTakeoverPage /> },
{ path: Routes.Session, element: <EmbeddedSessionPage /> },
{ path: Routes.PostSession, element: <PostSessionPage /> },
{ path: Routes.Sessions, element: <SessionsPage /> },
{ path: Routes.Profile, element: <ProfilePage /> },
{ path: Routes.ContentLibraryDetail, element: <ContentLibraryDetailPage /> },
{
path: Routes.Stats,
element: <StatsPage />,
children: [
{
path: Routes.BloodPressureStats,
element: <StatsPage.BloodPressureChart />,
index: true,
},
{ path: Routes.WeightStats, element: <StatsPage.WeightChart /> },
{ path: Routes.MoodStats, element: <StatsPage.MoodChart /> },
{
path: Routes.PhysicalActivityStats,
element: <StatsPage.PhysicalActivityChart />,
},
{
path: Routes.HeartRateStats,
element: <StatsPage.HeartRateSessionsView />,
},
{ path: Routes.HeartRateStatsDetail, element: <StatsPage.HeartRateSignalsView /> },
{
path: Routes.BloodOxygenStats,
element: <StatsPage.BloodOxygenSessionsView />,
},
{
path: Routes.BloodOxygenStatsDetail,
element: <StatsPage.BloodOxygenSignalsView />,
},
{
path: Routes.StepsStats,
element: <StatsPage.StepsChart />,
},
{
path: Routes.SleepStats,
element: <StatsPage.SleepChart />,
},
],
},
],
},
],
},
{ path: '*', element: <NotFoundPage /> },
];
return useRoutes(elements);
}

ReactJs not displaying route children - useRoutes

I am having a problem where children element of the route not displaying in the correct URL as example like if my URL is http://localhost:3000/dash by default it will go to http://localhost:3000/dash/default. I even already put the component in the children element. I am trying to wrap the children element with DashboardLayout and render its children inside DashboardLayout. I dont get a clue on this problem.
Below are code from the file
routes.js
export const routes = [
{
path: "dash",
element: <DashboardLayout />,
children: [
{
path: "*",
elment: <Navigate to={"/dash/default"} />,
},
{
path: "",
element: <Navigate to={"/dash/default"} />,
},
{
path: "default",
element: <Home />,
},
],
},
{
path: "*",
children: [
{
path: "*",
element: <Home />
},
],
},
];
Dashboardlayout.js
const DashboardLayout = ({ children }) => {
<React.Fragment>
<div>{children}</div>
</React.Fragment>;
};
export default DashboardLayout;

How to lazy load route with react location?

I am quite new to React, and I have a project that uses react-location
I would like to load some routes lazily only if the path is activated.
My current config is:
my base routing module
export const routes: Route[] = [
...HomeModuleRoutes, // I want this to be instantly loaded.
...LazyRoutes, // I want this to be lazy loaded.
{ path: '/', element: <Navigate to="/home" /> },
];
those 2 constants look like this :
home.routing.ts
export const routes: Route[] = [
{
path: 'home',
element: <HomeTemplate />,
children: [
{
path: '/',
element: <HomePage />,
},
],
},
];
lazy.routing.ts
export const LazyRoutes: Route[] = [
{
path: 'test',
element: <LazyTemplate />,
children: [
{
path: '/',
element: <LazyList />,
},
{
path: 'add',
element: <LazyAdd />,
},
{
path: 'detail',
element: <LazyDetail />,
},
],
},
];
I don't quite see documentation or an example on this, is it just wrapping the component with <Suspense>?
You should import your component with React.lazy like:
const HomeTemplate = React.lazy(() => import("./HomeTemplate "));
check this example for react-router v6 lazy loading

Delete `,` prettier/prettier and Parse errors in imported module './routes'

I download a MUI template for a React web-base app.
In Routes.js file, I commented out a line
and deleted the "," before this line. Later I uncomment the line and add the ",", so it looks the same as before; however, there is an issue as follows: when npm start, it fails to compile.
I'm beginner for reactjs and can't understand what this means.
src\App.js
Line 2:20: Parse errors in imported module './routes': Unexpected token, expected "," (26:8) (26:8) import/no-named-as-default
Line 2:20: Parse errors in imported module './routes': Unexpected token, expected "," (26:8) (26:8) import/no-named-as-default-member
src\routes.js
Line 24:52: Delete `,` prettier/prettier
Line 36:55: Delete `,` prettier/prettier
Search for the keywords to learn more about each error.
routes.js is as follows:
import { Navigate, useRoutes } from 'react-router-dom';
// layouts
import DashboardLayout from './layouts/dashboard';
import LogoOnlyLayout from './layouts/LogoOnlyLayout';
//
import Login from './pages/Login';
import Register from './pages/Register';
import DashboardApp from './pages/DashboardApp';
import Products from './pages/Products';
import Blog from './pages/Blog';
import User from './pages/User';
import NotFound from './pages/Page404';
// ----------------------------------------------------------------------
export default function Router() {
return useRoutes([
{
path: '/dashboard',
element: <DashboardLayout />,
children: [
{ element: <Navigate to="/dashboard/app" replace /> },
{ path: 'app', element: <DashboardApp /> },
{ path: 'user', element: <User /> },
{ path: 'products', element: <Products /> },
// { path: 'blog', element: <Blog /> },
]
},
{
path: '/',
element: <LogoOnlyLayout />,
children: [
{ path: 'login', element: <Login /> },
{ path: 'register', element: <Register /> },
{ path: '404', element: <NotFound /> },
{ path: '/', element: <Navigate to="/dashboard" /> },
{ path: '*', element: <Navigate to="/404" /> },
]
},
{ path: '*', element: <Navigate to="/404" replace /> }
]);
}
I fixed this question by adding two lines in .eslintrc file
"import/no-named-as-default": 0,
"import/no-named-as-default-member": 0,
that means, I unactive that two rules so no compliling error will be caused by these two rules

How to pass Props into React Router 6 so it can be accessed in mapStateToProps(state,ownProps)?

I am using redux for one of my component. In mapStateToProps I like to use the id of the URL Params, but in no ways I am able to get the id of the url in that function.
function mapStateToProps(state, ownProps) {
**const recId = ownProps.id;**
const reconciliationRule =
recId && state.reconciliationRules.length > 0
? getReconciliationById(state.reconciliationRules, recId)
: newReconciliationRule;
return {
reconciliationRule,
reconciliationRules: state.reconciliationRules,
};
My route.js looks like below
const routes = [
{
path: "app",
element: <DashboardLayout />,
children: [
{ path: "dashboard", element: <DashboardComponent /> },
{ path: "reconciliations", element: <ReconciliationComponent /> },
***{ path: "reconciliationRule/:id", element: <RulesComponent /> },***
{ path: "help", element: <HelpComponent /> },
{ path: "reports", element: <ReportComponent /> },
{ path: "settings", element: <SettingsComponent /> },
{ path: "billing", element: <BillingComponent /> },
{ path: "*", element: <Navigate to="/404" /> },
],
}
]
See if you see I want to send { path: "reconciliationRule/:id", element: } into RulesComponent
Static props I can send easily e.g.
{ path: "reconciliationRule/:id", element: <RulesComponent staticId={1}/> }
I can access this in mapStateToProps, but question is how to pass an ID of URL in react-router-dom.
Tried lot of permutation and combination but unable to solve it.
Don't want to switch to rr5 or rr4 where I can do this using rendering, but I need this to be done rr6.
Any help in this regards will be appreciated.

Resources