Sugarcoating for react router
npm install --save @react-augment/react-router
import AugmentRouter from '@react-augment/react-router'
const Home = () => (<div>Home</div>);
const About = () => (<div>About</div>);
const App = () => {
return <AugmentRouter routes={[
{ exact: true, path: '/', component: Home },
{ path: '/about', component: About }
]}/>
}
You can add middleware to your routes and use react-augment's builtin middleware functions
middleware: [...]
You can redirect users from your middleware when their login status changes using the jsx**redirect**
middleware function.
{ exact: true, path: '/home', component: () => (<div>Session: {session}</div>),
middleware: [
execute(() => {
if ( inSession === true ) {
return redirect('/login')
}
}),
]},
{ path: '/login', component: () => (<div>Login</div>) },
]}
A component can be updated, on a given path, using async components.
<AugmentRouter routes={[
{ path: '/', component: () => (<div>Session: {session}</div>), middleware:
[
execute(() => {
return new Promise((resolve, reject) => {
// maybe dispatch some action here.
setTimeout(() => {
resolve();
}, 3000)
})
}),
asyncComponent(() => <div>Logged in as: {session}</div>),
]},
{ path: '/about', component: () => (<div>About</div>) },
]}
Middleware will execute sequentially. eg.
middleware: [ m1, m2, m3 ]
the first middleware function to execute would be m1, the m2 and vice versa. By default middlware functions will keep executing even when one of the encounters an excetion or a redirect middleware function is returned.
To optionally break the execution chain on exception, pass true to execute middleware function as a second argument.
Eg.
execute(() => {}, true);
Whenever a middleware execute function returns a value, it's passed to the middleware function that's sitting ahead of it in the execution order. In the next middleware function that receives this value, if it's the execute function, it's accessable via it's first parameter of the async function passed to execute.
execute((previousMiddlewareReturnValue) => {...})
Whenever a middleware execute function encounters an exception, to handle it, another execute middleware can be passed to the execution chain. This function will have any exception values thrown by the previous execute middleware function.
execute((previousMiddlewareReturnValue, previousMiddlewareException) => {...})
Such a functionality can be used to display an error message or log something incase of an exception and optionally continue the execution chain.
By default, the components passed to react router have browser history object passed in their props. The history object can be used to perform navigation.
component: ({ history }) => (<.../>)
You can get a hold of a reference to browser router by passing a ref object to AugmentRouter ref prop.
<AugmentRouter ref={ref} ... />
Browser router props can be supplied to the augment router using browserRouterProp prop.
Typescript support added.
import types via jsx import {...} from '@react-augment/react-router/dist/types'
- AugmentRouterType
- AugmentComponentType
- AugmentRouteType
###### Clean code and decorator alternative
You can use higher order functions as a clean alternative to decorators and use them across both javascript and typescript with ease.
This acts as a wrapper around your main router component and will wrap your main app component with the augment router. The router hof accepts the same props that the Augment component does except the preload component prop. So whichever component you supply
eg.
import React from 'react';
import { augmentRouter } from '@react-augment/react-router';
// import { AugmentComponentType } from '@react-augment/react-router/dist/types';
const WrapperComponent = () => (<></>);
// routes are now optional but either require atleast one hof route or an empty array in the router hof.
const App = augmentRouter({
routes: [...],
// other props
....
})(WrapperComponent);
// if you dont want to wrap augment's main navigator, you can simply call the augment router hof without a wrapper
//const App = augmentRouter({
// routes: [...],
// // other props
// ....
//})();
Wanna use something similar to anular decorators but don't want to go through the headache of setting up decorators and avoid pitfalls of using experimental decorators.
You can wrap your components up in augmentComponent
hof and export all your wrapped component in an index file in your component root directory and simply import this directory where you're setting up the router.
eg. components/home.tsx
import { augmentComponent } from '@react-augment/react-router';
import { AugmentComponentType } from '../../../dist/types';
const HomeComponent = ({ history }:AugmentComponentType) => {
return (
<div>Home <i onClick={() => history.push('/about')}>To about</i></div>
);
}
export default augmentComponent({
exact: true,
path: '/',
middleware: []
})(HomeComponent);
components/about.tsx
import { execute } from '@react-augment/react-router';
import { augmentComponent } from '@react-augment/react-router';
const AboutComponent = ({ history }: any) => {
return (
<div>About <span onClick={() => history.push('/')}>To home</span></div>
);
}
export default augmentComponent({
path: '/about',
middleware: [ execute(() => console.log('middleware about page')) ]
})(AboutComponent);
components/index.ts
export * from './home';
export * from './about';
...
main router file eg. App.tsx
import './components';
import { augmentRouter } from '@react-augment/react-router';
// import { AugmentComponentType } from '@react-augment/react-router/dist/types';
// you can use wrapper components to update app states etc from the main nav.
// const WrapperComponent = () => (<></>);
const App = augmentRouter({})();
And Voilà... That's it. You're good to go.
True MVC suppport by introducing controller logic.