@jerrywithaz/better-react-router-routing
TypeScript icon, indicating that this package has built-in type declarations

1.4.2 • Public • Published

Better React Router Routing

Centralized and accessible routing for React Router. Better React Router Routing allows you to centralize your react-router routes in a configuration file and render nested routes with ease. It also provides an easy way to capture invalid routes and secure routes that require authentication. In addition, better react router routing ensures that your routing is accessible to users using a screen reader.

Installation

yarn add @jerrywithaz/better-react-router-routing

npm install @jerrywithaz/better-react-router-routing

Usage

Define your routes

import { RouteConfig } from "@jerrywithaz/better-react-router-routing";
import HomeView from "./views/HomeView";
import LoginView from "./views/LoginView";
import UserView from "./views/UserView";
import Dashboard from "./components/Dashboard";

const routes: RouteConfig[] = [
  {
    key: "route-base-view",
    secure: false,
    path: "/",
    exact: true,
    component: LoginView,
    a11yMessage: "You have navigated to the Home Page",
    title: "JerryWithaZ - Home"
  },
  {
    key: "route-login-view",
    secure: false,
    path: "/login",
    component: LoginView,
    exact: true,
    a11yMessage: "You have navigated to the Login Page",
    title: "JerryWithaZ - Login"
  },
  {
    key: "route-home-ui",
    secure: true,
    path: "/home",
    component: Dashboard,
    exact: false,
     a11yMessage: "You have navigated to the Home Page",
    title: "JerryWithaZ - Home",
    routes: [
      {
        key: "route-home-view",
        secure: true,
        path: "/home",
        component: HomeView,
        exact: true,
        a11yMessage: "You have navigated to the Home Page",
        title: "JerryWithaZ - Home"
      },
      {
        key: "route-home-user-view",
        secure: true,
        path: "/home/user",
        component: UserView,
        exact: true,
        a11yMessage: "You have navigated to the User Page",
        title: "JerryWithaZ - User"
      }
    ]
  }
];

export default routes;

Setup your app and render your routes

Better React Routing is unopnionated about your authentication protocol. The only thing we need is a boolean that indicates whether or not a user is authenticated. In the demo below we are using an example redux provider and a useAuthenticated hook that grabs the authentication status from the store and returns a boolean. Any route that is marked as secure will render the UnauthorizedRedirect component if not authenticated. By default it just redirects the user to /login. But, you can customize the redirect path by pasing either a string or function to the redirectPath prop of BetterReactRoutingProvider.

import BetterReactRoutingProvider, { Switch, Capture404 } from '@jerrywithaz/better-react-router-routing';

function useAuthenticated(): boolean {
  const authenticated = useSelector((state: AppState) => state.auth.authenticated);
  return authenticated;
}

const AppRoutes: FunctionComponent = () => {

    const authenticated = useAuthenticated();  

    function redirectPath(componentProps: any) {
        if (componentProps.invitationCode) {
            return `/invitation?code=${componentProps.invitationCode}`;
        }
        return "/login";
    }

    return (
      <BetterReactRoutingProvider
        authenticated={authenticated}
        initialA11yMessage={"Welcome to Koddi"}
        initialDocumentTitle={"Koddi"}
        routes={routes}
        FoundComponent={() => <Switch routes={routes} />}
        NotFoundComponent={() => <div>Page not found</div>}/>
    );
}

function App() {

  return (
    <ReduxProvider>
      <RouterProvider history={history}>
        <GlobalStyles />
          <Styled.App>
            <AppRoutes/>
          </Styled.App>
      </RouterProvider>
    </ReduxProvider>
  );
}

Nested Routes (Subroutes)

When using nested routes (subroutes) you will need to use the Switch component to render those routes.

Let's say this is your routes config:

const routes: RouteConfig[] = [
  {
    key: "route-home-ui",
    secure: true,
    path: "/home",
    component: Dashboard,
    exact: false,
    routes: [
      {
        key: "route-home-view",
        secure: true,
        path: "/home",
        component: HomeView,
        exact: true
      },
      {
        key: "route-home-user-view",
        secure: true,
        path: "/home/user",
        component: UserView,
        exact: true,
        redirectPath: () => "/signup"
      }
    ]
  }
];

The Dashboard component will need to render Switch with the routes prop it will recieve.

It would look something like this:

import { Switch, RouteConfigComponentProps } from '@jerrywithaz/better-react-router-routing';

const Dashboard = ({
    routes
}: RouteConfigComponentProps) => {
    return (
        <Styled.Dashboard>
            <DashboardSidebar/>
            <DashboardMain>
                <Switch routes={routes}/>
            </DashboardMain>
        </Styled.Dashboard>
    );
}

Securing Routes with Permissions or Roles

Often times you only want users to be able to access a route only if they have certain roles or permissions. Better React Routing makes that easy to do.

NOTE When a user has insufficient permissions or roles null is rendered by default. So, be sure to pass in a fallback component by either using the fallback component on the BetterReactRoutingProvider or on the route itself.

Setting Permissions and Roles

You will need to pass the current users permissions or roles to the BetterReactRoutingProvider.

  <BetterReactRoutingProvider
    authenticated={authenticated}
    initialA11yMessage={"Welcome to Koddi"}
    initialDocumentTitle={"Koddi"}
    routes={routes}
    FoundComponent={() => <Switch routes={routes} />}
    NotFoundComponent={() => <div>Page not found</div>}
    permissions={["admin.read", "admin.write", "theme.write", "users.delete"]} // the current users permissions
    roles={["Admin", "Developer"]} // the current users roles
    FallbackPermissionsComponent={() => <div>You do not have permission</div>}
    FallbackRolesComponent={() => <div>You do not have the correct role.</div>}/>
);

Route Specific Fallback Components

You can set fallback components per route if you want to cusrtomize the error message.

const routes: RouteConfig[] = [
  {
    key: "route-base-view",
    secure: false,
    path: "/admin",
    exact: true,
    component: LoginView,
    permissions: ["admin.read", "admin.write"],
    roles: ["admin"],
    requireAllPermissions: true,
    requireAllRoles: true,
    fallbackPermissionsComponent: () => <div>You do not have permission.</div>,
    fallbackRolesComponent: () => <div>You do not have the correct role.</div>,
    a11yMessage: "You have navigated to the Home Page",
    title: "JerryWithaZ - Home"
  },
  {
    key: "route-login-view",
    secure: false,
    path: "/dev",
    component: LoginView,
    permissions: ["dev.read", "dev.write", "dev.delete"],
    roles: ["dev"],
    requireAllPermissions: false,
    requireAllRoles: true,
    exact: true,
    a11yMessage: "You have navigated to the Login Page",
    title: "JerryWithaZ - Login"
  }
];

Global Fallback Components

Setting the fallback components on the provider will be used as the default fallback components. The global fallback component will be overriden by route specific fallback components.

  <BetterReactRoutingProvider
    authenticated={authenticated}
    initialA11yMessage={"Welcome to Koddi"}
    initialDocumentTitle={"Koddi"}
    routes={routes}
    FoundComponent={() => <Switch routes={routes} />}
    NotFoundComponent={() => <div>Page not found</div>}
    FallbackPermissionsComponent={() => <div>You do not have permission</div>}
    FallbackRolesComponent={() => <div>You do not have the correct role.</div>}/>
);

Package Sidebar

Install

npm i @jerrywithaz/better-react-router-routing

Homepage

/

Weekly Downloads

54

Version

1.4.2

License

ISC

Unpacked Size

91.5 kB

Total Files

100

Last publish

Collaborators

  • zerryhogan