rift-router
Version:
Blazing Fast and Lightweight router for React Based on state first.
193 lines (152 loc) • 5.95 kB
Markdown
# rift-router  [](https://github.com/prettier/prettier) [](https://travis-ci.org/Cervantes007/rift-router) [](https://codecov.io/gh/Cervantes007/rift-router)
Blazing Fast and Lightweight router for React Based on state first..
## Features
- Lightweight 1.8kb (min/gzip) - 5kb (min)
- No Dependencies
- Blazing Fast update app state first and then Browser Sync.
- Useful route information in `params`, `search`, `path` and `active` router properties.
- Typescript first class, but works fine with javascript too.
- Nesting Route.
- Lazy loading for route component.
- Hooks `onEnter` and `onLeave`.
- Redirect.
- Route Guard.
- Automatic Browser Sync
- Isomorphic.
## Installation
`npm i -s rift-router`
## Usage
```typescript
import React, {lazy} from 'react';
import ReactDOM from 'react-dom';
import { IRiftRoute, RiftProvider, RiftGate, RiftLink } from 'rift-router';
const Home = () => <div>'Home Component'</div>;
const About = () => <div>'About Component'</div>;
const routes: IRiftRoute[] = [
{ path: '/', component: <Home /> },
{ path: '/about', component: () => <About /> },
{ path: '/users', component: lazy(() => import('./users')),
];
ReactDOM.render(
<RiftProvider routes={routes} fallback={<div>loading...</div>}>
<RiftLink to="/">Home</RiftLink>
<RiftLink to="/about">About</RiftLink>
<RiftGate /> {/* render the component for current route */}
</RiftProvider>,
document.getElementById('root')
);
```
Check basic usage in a sandbox:
[](https://codesandbox.io/s/myq5nowwwp)
#### and that's it, try it.
## Routes object options.
#### Using Hooks:
```typescript
function isUserLogged() {...}
const routes = [
{
path: '/users',
component: <UserList />,
onLeave: () => '...Do some logic when current route will change',
onEnter: () => {
if(!isUserLogged()) {
return '/login';
}
}
}
]
```
`onEnter` run just before set new route, therefore it can be used as route Guard, if `onEnter` return an string value, the router will redirect to this value.
#### Handle route not match
```typescript
const routes = [
// Default route (*) redirect to '/'
{ path: '*', onEnter: () => '/' },
// Default route keep browser url and show Home component
{ path: '*', component: <Home /> },
// Default route show Not Found Page component
{ path: '*', component: <NotFound404 /> },
];
```
#### Nesting routes
```typescript
const routes: IRiftRoute[] = [
{
path: '/admin',
component: () => 'admin',
children: [
{
path: '/users',
component: () => 'users',
},
{
path: '/users/:id?',
component: () => 'users editor',
},
],
},
];
```
`note:` For each nesting you must place a `<RiftGate/>` component to display current nesting component.
#### Building your routes with many files and lazy loading components.
```typescript
// somewhere in the users module/folder
export const usersRoutes = [
{
path: '',
component: React.lazy(import('./UserList')),
},
{
path: '/:id',
component: React.lazy(import('./UserDetails')),
},
];
```
```typescript
// building your routes with others routers files.
const routes: IRiftRoute[] = [
{
path: '/users',
children: usersRoutes,
},
];
```
Lazy loading your component will reduce the first load time, therefore your page will be show faster, then other component will be load in demand.
Caveat: `React.lazy and Suspense are not yet available for server-side rendering. If you want to do code-splitting in a server rendered app check <a href="https://reactjs.org/docs/code-splitting.html#reactlazy">here</a>`
### `router` instance API:
- `path` (show current path - `router.path` -> '/users')
- `params` (for path = `/users/:id` - current route = 'users/5' -> `router.params` = `{id: 5}`)
- `search` (for route = `/users?from=home` -> `router.search` = `{from: "home"}`)
- `to` function receive a `string` parameter for navigate to (router.to('/users'))
## How to get router object
Option 1: In your component use the router from RiftContext using useRouter hook.
```typescript
const Home = () => {
const router = useRouter();
const toAbout = () => router.to('/about');
return (
<div>
<div>Home Component</div>
<button onClick={toAbout}>About us</button>
</div>
);
};
```
Option 2: In your route inject the router instance as a `component` prop, same for `onEnter` and `onLeave` hooks
```typescript
const routes: IRiftRoute[] = [
{ path: '/', component: <Home />, onEnter: router => {...} },
{ path: '/about', component: router => <About router={router} /> },
];
```
## How it Work.
1. Pass your `routes` to `RiftProvider` and it will create a router instance and share it through `React.Context` to be use deep in the component tree
with the `useRouter` hook.
`RiftProvider` also accept a `fallback` prop where you can provide a component to will be shown by all yours `RiftGate` while lazy components finish to load.
2. `RiftGate` works as a gateway to show the correct component for the active route. If you have nesting routes you must
use the same number of `RiftGate` to render the nested components in the active route. Also accept a `fallback` prop
where you can provide a component to show while lazy components finish to load, this will override the `fallback` of the `RiftProvider`.
## TODO:
#### Add Documentation for
- [x] Code Splitting.
- [ ] Server Side Rendering Example.