A route configuring, rendering and guarding lib based on React Router

? Config Router ?

A route configuring, rendering and guarding lib based on React Router v5.x.

Why Config Router? ?

Config Router ? is an attachment lib to React Router v5.x. It works well with React Router, helping with route configuration, route rendering and route guarding.

If you are a Vue Router user before, it is quite easy for you to get started. Of course this project is not as mature as Vue Router. ?

Features ?

  • ✔️ Config route by declaring the routes array like that in Vue Router.
  • ✔️ Render routes by importing and using a single component called RouterView ?.
  • ✔️ Guard routes that should be accessed only by authorized users.
  • ⭕ More is on the way…

Usage ?

You can use this package in either react-jsx projects or react-tsx projects. Take project with vite, react and typescript for example.

Add React Router Dependencies

yarn add -s react-router-dom
yarn add -D @types/react-router-dom

Or with npm.

npm i -s react-router-dom
npm i -D @types/react-router-dom

Add Config Router Dependencies

After adding React Router dependencies, you can add config-router to your project.

yarn add -s @syy11cn/config-router

Or with npm.

npm i -s @syy11cn/config-router

Create a Configuration File

Create a configuration file in src/routes (for example config.ts).

Here is a sample configuration.

// First you should import `routeType`.
import { routeType } from '@syy11cn/config-router';
// Import components to be used.
import Index from '../views/Index';
import Portal from '../views/Portal';
import Test from '../views/Test';
import Error from '../views/Error';

// Routes config.
const routes: Array<routeType> = [
  {
    path: '/home',
    component: Index,
    routes: [
      {
        path: '/home/test',
        component: Portal,
      },
      {
        path: '/home',
        component: Test,
      },
    ],
  },
  {
    path: '/404',
    component: Error,
  },
  {
    path: '/',
    component: Portal,
  },
];

export default routes;

As shown above, routes config is an array consists of routeType items.

routeType is declared as follows,

import * as React from 'react';

interface routeType {
  path: string;
  component: React.ComponentType<any>;
  exact?: boolean;
  routes?: Array<routeType> | undefined;
}

export default routeType;

which means the routes field of an item is another routeType array.

Prompt in Writing Configuration

  • The root route should always be the last item in a routeType array.
  • Never set exact: true when there is a routes field in the routeType item.
  • Fields path and component are required. Fields exact and routes are optional.

Use RouterView Component

In main.tsx, add <Router> outside the <App> Component.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter as Router } from 'react-router-dom';

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <App></App>
    </Router>
  </React.StrictMode>,
  document.getElementById('root')
);

Then in App.tsx, use RouterView component.

import { FunctionComponent } from 'react';
import { Layout } from 'antd';
import { RouterView } from '@syy11cn/config-router';
import routes from './routes/config';
import './App.css';

const { Header, Content, Footer } = Layout;

interface AppProps {}

const App: FunctionComponent<AppProps> = () => {
  return (
    <div className="App">
      <Header></Header>
      <Content>
        <RouterView
          routes={routes}
          onEnter={function (to, next): void {
            console.log('onEnter');
            next();
          }}
        ></RouterView>
      </Content>
      <Footer></Footer>
    </div>
  );
};

export default App;

The RouterView component here would render routes in the <Content> component. Rendered components would take the place of RouterView.

Nested Routes

In the sample configuration, there is a nested route in component Index. Notice that no matter where you use a RouterView, there should be a routes attribute added on it.

Therefore, in src/views/Index.tsx, the component should receive a routes property, which includes nested routes under Index component.

import { FunctionComponent } from 'react';
import { RouterView } from '../routes';
import { routeType } from '@syy11cn/config-router';

interface IndexProps {
  routes: Array<routeType>;
  props: any;
}

const Index: FunctionComponent<IndexProps> = ({ routes, props }) => {
  console.log('Index View');
  return (
    <div>
      <h1>This is Index</h1>
      <RouterView
        routes={routes}
        onEnter={(to, next) => {
          if (to === '/home/test') {
            next();
          } else {
            next('/404');
          }
        }}
      ></RouterView>
    </div>
  );
};

export default Index;

Route Guarding

Write a Function in onEnter hook, and the Function would be called before rendering the routes.

Your Function should receive two properties, which are named to and next.

  • to is a string referring which route a user want to meet.
  • next is a Function. If you pass a string to it, next would help you redirect to that path. While if you call next without passing a property, the component would just let user go where they want.

The same sample code as above.

import { FunctionComponent } from 'react';
import { RouterView } from '../routes';
import { routeType } from '@syy11cn/config-router';

interface IndexProps {
  routes: Array<routeType>;
  props: any;
}

const Index: FunctionComponent<IndexProps> = ({ routes, props }) => {
  console.log('Index View');
  return (
    <div>
      <h1>This is Index</h1>
      <RouterView
        routes={routes}
        onEnter={(to, next) => {
          if (to === '/home/test') {
            next();
          } else {
            next('/404');
          }
        }}
      ></RouterView>
    </div>
  );
};

export default Index;

In this situation, when a user want to access /home/test, corresponding route and component would be rendered. When accessing /home or other routes begin with /home, the user would be redirect to a 404 page.

Contribution ?

Contributions are welcome. Just fork this repo and send PRs.

Any questions while using this package, please open an issue and I would manage to solve it as soon as I receive the message.

About ?

License

MIT

Copyright (c) 2021, Yiyang Sun

GitHub

View Github