UNPKG

rift-router

Version:

Blazing Fast and Lightweight router for React Based on state first.

193 lines (152 loc) 5.95 kB
# rift-router ![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) [![Build Status](https://travis-ci.org/Cervantes007/rift-router.svg?branch=master)](https://travis-ci.org/Cervantes007/rift-router) [![codecov](https://codecov.io/gh/Cervantes007/rift-router/branch/master/graph/badge.svg)](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: [![Edit RiftRouter Basic](https://codesandbox.io/static/img/play-codesandbox.svg)](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.