Router with Guard — Takeaway routing solution for React project
Routing has always been a key aspect in developing web. There are many requirement in routing: code splitting, route guard, nested route, default loading screen…
With the react-router-guard, we hope to help you achieve all mentioned above with the least amount of effort, with all the logic needed grouping in one place
Link gitHub: https://github.com/laptransang/react-router-guard
1. Before react-router-guard
With the react-loadable recommended in the React document and given a ‘Home Page’ container component in HomePage.js like this:
function HomePage(props) {
return (<div> Greeting at my door </div>)
}
For a basic routing, you made a route.js file:
import Loadable from ‘react-loadable’;
import Loading from ‘./my-loading-component’;
And to do the code splitting with that you made a route.js:
const HomePageComponent = Loadable({
loader: () => import(‘./HomePage’),
loading: Loading,
});class App extends Component {
render() {
<Router>
<Route exact path=”/” component={HomePageComponent} />
</Router>
}
}
That is just for the basic, now you want to add constraint on accessing the route. Given the scenario when I only want the logged in user to have the ability to access to ‘/profile’ route now you will create more HOC to make a fallback component:
// get the user's credential from local storage
import { getUserProfile } from 'utils';
function checkAuth(
FallbackComponent,
...rest,
) {
const profile = getUserProfile();
if (!profile) {
return FallbackComponent
? <FallbackComponent {…rest} />
: <Redirect to="/" />
}
}
export default checkAuth();
Then in the route.js, wrap the dynamic loaded component with the new HOC:
import CheckAuth from 'guards/checkAuth';
const ProfilePage = Loadable({
loaded: () => import ('./ProfilePage'),
loading: Loading,
});const ProfilePageFallback =
class App extends React.Component {
render() {
…
<Route exact path='/profile' component={ProfilePageFallback}/>
…
}
}
All of that just to have a guard on the registering route. You have to dynamic import in one place, wrap it in another and finally assign the url path in a component. Technically you can merge all the work in to one line of code but it would be a matter of nightmare
And now I introduce you — the react-router-guard library
2. The library we need and the library we deserve
Once installed, all the code written above can be reduced to this:
import { dynamicWrapper } from 'react-router-guard';
import { checkAuth } from "./guard";
In the config file:
export default [
{
path: '/',
component: dynamicWrapper(() => import ('./HomePage')),
},
{
canActivate: checkAuth,
path: '/',
component: dynamicWrapper(() => import ('./ProfilePage')),
},{
canActivate: checkNotAuth,
path: '/',
component: dynamicWrapper(() => import ('./SignInPage')),
}
]
About the checkAuth:
In the app file, just nest the route into one common browser
import {BrowserRouter} from 'react-router-dom';
import RouterGuard from ‘react-router-guard’;function App() {
return (
<BrowserRouter>
<RouterGuard config={config} />
</BrowserRouter>
)
}
As you can see, all the configs are now combined into one config object. And the guards (which is listed as single/array element in the canActivate props) are promises. Those promises let the navigation pass if they resolve(true) and redirect to the error thrown by reject(‘path’)
Beside one primary purpose of a cleaner routing system set up and guards, the library also have different interesting feature that may come in handy in developing web, such as:
- Default or customized loading UI component on unfinished routing
- Template for nested route
- Dynamic redirect with parameters
Find more about us and checkout the demo by going to https://github.com/laptransang/react-router-guard/blob/master/README.md
Let me know what’s good and what’s not by commenting below.
Once again, don’t forget to download the library and test it yourselves