React Spa Router
Router for React applications:
- 2 modes : hash and history
- page animation/transition with css or js
- activeClassName
- route guards
- children
- named views
- actions
Installation
npm i react-spa-router -S
Imports
;
Router & route configs
Router config | Description |
---|---|
routes | routes array |
mode | hash (by default) and history (html5 history). |
scroll | handle navigation to fragment (true by default) |
Route config | Description |
---|---|
path | the path pattern ("/posts" or "posts/:id" or "/posts/:id([a-z]+)" for example) |
name | route name |
action | an action |
actions | an array of actions |
data | extra data to pass |
canActivate | route guards |
canActivateChild | route guard for children |
canDeactivate | route guards |
redirectTo | redirect to route url |
children | nested routes |
Resolved Route | Description |
---|---|
url | full url |
path | path string |
params | params object |
queryString | query string |
query | query object |
fragment | fragment |
matched | matched Route config |
Action parameters | Description |
---|---|
route | resolved route |
router | router |
result | previous action result |
error | previous action error / rejection |
Example create routes
const routes = path: '/' path: '/posts' canActivate: MyGuard canDeactivate: MyGuard path: '/posts/:id' name: 'about' path: '/about' path: 'customers' children: path: '' actions: console path: ':id' actions: console path: '**' redirectTo: '/' ;
An action return the previous action result (or error / rejection). Example:
const routes = path: '/' actions: 'My result' console ;
Chaining promises, async/ await, simple returned values ...
{ return { ; };} const routes = path: '/' actions: // with promise { return { ; }; } // with async await async { // result 1 return await ; } // simple result { // result 2 return 'result 3'; } { // result 3 return { ; }; } console // result 4 ;
Lazy loading with Webpack
Create a component About that receive a background color
Use Webpack to resolve this component only when needed (dont import component) (code splitting)
const resolveAbout = { require;};
Route
const routes = path: '/' name: 'about' path: '/about' { // lazy loading ; } ;
Create a router (in App component)
Component<any any> { superprops; const router = mode: 'history' routes ; } { return <div className='container'> <nav> <ul> <Link tag='li' to='/' activeClassName='active'>Home</Link> <Link tag='li' to='/posts' activeClassName='active'>Post list</Link> <Link tag='li' to='/posts/10' activeClassName='active'>Detail</Link> <Link tag='li' to= path: '/posts/50' query: q: 'mysearch' fragment: '#section1' activeClassName='active' activePattern=/\/posts\/0-9+/}>Query+fragment and active pattern</Link> <Link tag='li' to='/customers' activeClassName='active' exact=false>Customers</Link> /* named route */ <Link tag='li' to= name: 'about' activeClassName='active'>About</Link> </ul> </nav> <RouterView className=thisstateselectedValue enter='navInPrev' leave='navOutPrev' enterTimeout=500 leaveTimeout=500 simultaneous=true /> /* named view*/ <RouterView name='customers' /> </div > ); }
Base Tag
Usefull to specifiy explicitly the base path of the site.
Example (in the head of the index.html page)
Router Link
With path
<Link to='/'>Home</Link>/* with params */<Link to='/posts/10'>Detail</Link>/* with query and fragment */<Link to='/posts/10?q=abc&cat=10#section1'>Detail</Link>
Or
<Link to= path: '/posts/10' query: q: 'mysearch' fragment: '#section1' >Detail</Link>
Named route
<Link to= name: 'about' activeClassName='active'>About</Link>
With params
thisstateposts
activeClassName
<Link to='/posts/10' activeClassName='active'>Detail</Link>
exact (by default is true)
Set exact to false
<Link to='/customers' activeClassName='active' exact=false>Customers</Link>
Pattern
Allow to define a regex to check active
<Link to='/posts/10' activeClassName='active' activePattern=/\/posts\/0-9+/}>Detail/Link>
Wrap link into an other element (tag)
Example link will be append to a li element. The activeClassName is added to li element.
<ul> <Link tag='li' to='/' activeClassName='active'>Home</Link></ul>
RouterView
Is the container for the "router-pages"
Default RouterView
<RouterView />
Named RouterView
<RouterView name='my-view' />
Change view component with "viewRender" function
/* or */
Change the content of a named view
Navigate programmatically
router;// or with named route (route name, params, query, fragment)router;
- replace, replaceUrl, goBack, goForward
Animate RouterView
Example a fadeIn, fadeOut
<RouterView enter='fadeIn' enterTimeout=1000 leave='fadeOut' leaveTimeout=1000 />
@} @}
Simultaneous animation
<RouterView className='fxShuffle' enter='navInPrev' leave='navOutPrev' enterTimeout=500 leaveTimeout=500 simultaneous=true />
JavaScript animation
Control animation with beforeEach, afterEach and error callback (page not found, navigation aborted with a guard)
const router = routes;
Route Guards
Create a class
{ let result = ; ; // could return true | false or string redirect url } { let component = activeComponents'PostList'; let result = component && componentcheckCanDeactivate ? component : true; ; }
Add the guard to check can activate and can deactivate a route
const routes = path: '/' path: '/posts' canActivate: MyGuard canDeactivate: MyGuard ;
Register a component with "setActiveComponent" function in order to access with the Guard
Component<any any> { superprops; ; } { return ; } { return <h1>Post list</h1> ; }
canActivateChild
Guard children
{ let result = ; ; }
Add guard to the parent route
const routes = path: '/' path: 'customers' canActivateChild: MyGuard children: path: '' actions: console path: ':id' actions: console ;
Auth flow
Guard
{ if auth ; else // add a query string with the url to redirect after the user will be logged in ; }
Routes
const routes = path: '/' canActivate: AuthGuard // inject the router and the route to the component path: '/signin' ;
Signin component
/* etc. */ { event; const email password = thisstate; auth; } /* etc. */;
With Redux
Example:
index.js
;;;;; ;; ;
routes.js
;; ;;; const routes = path:'/' path: '/movie' path: '/about' ;
App.js
;;;; ; Component { superprops; const router = mode: 'history' routes ; } { return <div> <Header /> <div className="container"> <RouterView /> </div> </div> ; };
etc.