All Projects → k1r0s → preact-routlet

k1r0s / preact-routlet

Licence: other
Simple `Component Driven` Routing for Preact/React using ES7 Decorators

Programming Languages

javascript
184084 projects - #8 most used programming language

Preact Routlet

This package contains routing functionalities for Preact and, now from 1.0.0 React applications as well. Instead of using HTML5 history API it uses the oldie /#/what-ever hash routing (this will change in the future).

This project was created by exploring contextual ways to define routes rather than placing all the routes in a single file.

Usage:

Available imports:

// if you're using React
import { renderOnRoute, navigate, RouterOutlet, PathLookup, routePool, Link } from "preact-routlet/react"
// if you're using Preact
import { renderOnRoute, navigate, RouterOutlet, PathLookup, routePool, Link } from "preact-routlet/preact"

Either from "preact-routlet/preact" or from "preact-routlet/react"

Place your RouterOutlet element somewhere in your JSX:

<div>
  <RouterOutlet />
</div>

Plug the renderOnRoute decorator on some component

@renderOnRoute("/login")
export default class Login extends Component<any, any> {
  ...
}

Remember to import your class to evaluate your component

import './components/login';

You dont need to instantiate or declare it. Just import it on your app index.

A good practice is to group your components by domain:

For example imagine the following index file:

import { h, render } from "preact";
import Main from "./common/main";

/* domain */
import "./domain/access";
import "./domain/dashboard";

render(<Main />, document.querySelector("#root"));

Then you have some kind of folder structure like this:

src/domain/
├── access
│   ├── index.tsx
│   ├── models
│   ├── pages
│   └── share
└── dashboard
    └── index.tsx

on each index file you're importing your components:

$ cat src/domain/access/index.tsx
import "./pages/login-page";
import "./pages/register-page";
import "./pages/forgot-password-page";

So basically you're registering all the components that listen to route changes in your app.

Features:

  • 404 routes: If none of the components are listening for some particular route

      <div>
        <RouterOutlet>
          <ThisComponentWillBeRenderedOtherwise />
        </RouterOutlet>
      </div>
  • Conditional rendering on route (declarative)

      <PathLookup shouldRender={path => predicate}>
        <ComponentThatWillBeRenderedIfPredicateReturnsTrue />
      </PathLookup>
  • Navigation (code)

      ...
      navigate("/somewhere");
  • Navigation (declarative)

      <Link href="/somewhere">Go to somewhere</Link>
  • Redirect if some condition was not fulfilled

    <RouterOutlet redirect="/login" shouldRedirect={path => requireLogin(path) && !AuthService.isLogged()} />
  • Lazy loading, Module splitting

By default routes are only loaded if you evaluate classes that contain the @renderOnRoute decorator, so simply by importing it. But you need the plugin syntax-dynamic-import to dynamically use the import() function with Babel.

...
} else if (User.isAdmin(userSnapshot)) {
 import('../admin'); //load admin module
}
// admin/index.js
...
import { navigate } from 'preact-routlet/react'; // import navigate function

import './dashboard'; //load component with @renderOnRoute
import './user-list'; //load component with @renderOnRoute

navigate('/admin-board'); //navigate to this module once routes are loaded

By using @renderOnRoute you're adding the evaluated component to the route pool

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].