Mongez React Router (MRR): Part-2

Mohamed Eltahawy
Jan 13
2 min read
post_comment0 Comments
post_like0 Likes

Route Middleware


Some routes require a step head before navigating to its component. for example the visitor can not access his/her account dashboard unless he/she is logged in, in such a scenario we can use a middleware.

// src/routes.ts
import router from "@mongez/react-router";

import AccountDashboardPage from "./pages/DashboardPage";
import EditProfilePage from "./pages/EditProfilePage";
import OrderHistoryPage from "./pages/OrderHistoryPage";
import SingleOrderHistoryPage from "./pages/SingleOrderHistoryPage";
import Guardian from "./middleware/Guardian";

router.add("/account", AccountDashboardPage, [Guardian]);
router.add("/account/edit-profile", EditProfilePage), [Guardian];
router.add("/account/order-history", OrderHistoryPage, [Guardian]);
router.add("/account/order-history/:id", SingleOrderHistoryPage, [Guardian]);

Here we defined our routes, with a new argument in router.add which is an array of middleware that will be declared before navigating to our pages.

Now let's see our new Guardian middleware file.

// src/middleware/Guardian.tsx
import user from "somewhere-in-the-app";
import React from "react";
import { navigateTo } from "@mongez/react-router";

export default function Guardian() {
  if (user.isNotLoggedIn()) {
    return navigateTo("/login");
  }

  return null;
}

Here we defined a component that allows us to check if user is not logged in, then we'll redirect the user to the login route by using navigateTo utility from MRR.

Now whenever a user hits any of the account routes, the Guardian component will be called first, if the user is not logged in then he/she will be redirected to the given route /login and called instead of the current page component.

If the middleware returned a value, then it will be displayed instead of the page component.

So the middleware can look like:

// src/middleware/Guardian.tsx
import user from "somewhere-in-the-app";
import React from "react";

export default function Guardian() {
  if (user.isNotLoggedIn()) {
    return <h1>You do not have access to this page, please login first.</h1>;
  }

  return null;
}

Page Base Layout

Most of the apps has same layout structure such as a header and a footer among it the content of the page.

This can be done easily with MRR by using router.partOf method.

// src/components/BaseLayout.tsx
import React from "react";
import Header from "./Header";
import Footer from "./Footer";

export default function BaseLayout({ children }) {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  );
}

Now let's add our New Base layout to our HomePage.

// src/routes.ts
import router from "@mongez/router";
import HomePage from "./pages/HomePage";
import BaseLayout from "./components/BaseLayout";

router.partOf(BaseLayout, [
  {
    path: "/",
    component: HomePage,
  },
]);

Now our HomePage component doesn't need to call the header or the footer of the page, it is now part of the BaseLayout.

Extending Base Layout

Let's take another scenario that the account pages have a common sidebar between all of its page, we can make a newer layout that can hold the header, footer and the account sidebar.

// src/components/AccountLayout.tsx
import React from "react";
import Header from "./Header";
import Header from "./Footer";
import AccountSidebar from "./AccountSidebar";

export default function AccountLayout({ children }) {
  return (
    <>
      <Header />
      <main>
        <AccountSidebar />
        <div>{children}</div>
      </main>
      <Footer />
    </>
  );
}

Now let's our account routes again to use our new layout instead of the base layout.

// src/routes.ts
import router from "@mongez/react-router";

import AccountDashboardPage from "./pages/DashboardPage";
import EditProfilePage from "./pages/EditProfilePage";
import OrderHistoryPage from "./pages/OrderHistoryPage";
import SingleOrderHistoryPage from "./pages/SingleOrderHistoryPage";
import Guardian from "./middleware/Guardian";

import AccountLayout from "./components/AccountLayout";

router.group({
  path: "/account",
  layout: AccountLayout,
  middleware: [Guardian],
  routes: [
    {
      path: "/",
      component: AccountDashboardPage,
    },
    {
      path: "/edit-profile",
      component: EditProfilePage,
    },
    {
      path: "/order-history",
      component: OrderHistoryPage,
    },
    {
      path: "/order-history/:id",
      component: SingleOrderHistoryPage,
    },
  ],
});

Now we're almost done, one more thing to do is to extend our base layout as we injected the header and the footer again in the AccountLayout component, let's fix this.

// src/components/AccountLayout.tsx
import React from "react";
import BaseLayout from "apps/front-office/components/BaseLayout";
import AccountSidebar from "./AccountSidebar";

export default function AccountLayout({ children }) {
  return (
    <BaseLayout>
      <AccountSidebar />
      <div>{children}</div>
    </BaseLayout>
  );
}

Now our code is very neat and can be maintained easily.

Embrace the power of Mongez React Router to enhance your React application's navigation structure, making it more readable, maintainable, and efficient. Whether you're a seasoned developer or just starting with React, MRR brings a set of features that can elevate your development experience. Explore the possibilities and navigate your React app with ease!

Wait for more, to be continued !

You are not logged in.