@composi/router is a client-side hash-based router for single page apps (SPA). This is for those occasions where you want to be able to conditionally render a set of sub components based on a url value. This is works properly with the browser's back button and you can use it with the History API. @composi/router is very simple with only a few options. If you need a more advanced router, check out Universal Router. Or use whatever router you prefer.
npm i -D @composi/router
Import Router
into your app.js
file:
import { h, render } from '@composi/core'
import { Router } from '@composi/router'
To create routes you need to instatiate Router and provide it with a series of path objects separated by commas. The path object is an object literal with a path and action value.
The following example shows how to set up routes. What you do when the route happens is completely up to you:
import { h, render } from '@composi/core'
import { Router } from '@composi/router'
// Create instance of Router:
const router = new Router()
// Define paths to use:
router(
{
path: "/",
action: () => {
// Do something when main page loads
}
},
{
path: "/about",
action: () => {
// load an "About" widget
}
},
{
// Capture a parameter id:
path: "/users/:name",
action: (name) => {
if (name === 'joe') alert('Hi, Joe!')
else console.log(name)
}
}
)
Normally you would use a route to handle loading a component. The easiest way to do this is to use a functional component:
import { h, render } from '@composi/core'
import { Router } from '@composi/router'
const router = new Router()
const Home = <h1>This is Home</h1>
const FirstPage = <h1>Welcome to the First Page!</h1>
const SecondPage = <h1>Second Page Here.</h1>
function Menu(props, child) {
return (
<div>
<ul class='menu'>
<li><a href="#/">Home</a></li>
<li><a href="#/first">First Page</a></li>
<li><a href="#/second">Second Page</a></li>
</ul>
{
child
}
</div>
)
}
function renderPage(component) {
render(<Menu>{component}</Menu>, 'section')
}
router(
{
path: '/',
action: () => renderPage(Home)
},
{
path: '/first',
action: () => renderPage(FirstPage)
},
{
path: '/second',
action: () => renderPage(SecondPage)
},
{
path: '/*',
action: () => {
console.log('Sorry, not a proper path.')
}
}
)
render(<Menu>{Home}</Menu>, 'section')
You could also use routes in conjuction with @composi/datastore. The route would set a value on the dataStore, which would cause the component to update.
You can use more than one handler for a route. You might do this because you need to remove some functionality later. If that's the case, you want to use named handlers for any handler you will want to remove:
// Handler to delete later:
const removableHandler = () => {
console.log('This handler is temporary and subject to removal.')
}
router(
{
path: '/',
action: () => console.log('You are home!')
},
{
path: '/',
action: () => console.log('This is another handler on the Home path.')
}
)
To learn more about removing paths and handlers, see Removing a Route
You can indicate that a parameter is optional by using the ?
character after it:
router({
path: 'users/:name?',
action: function(name) {
if (name) {
console.log(name)
} else {
console.log('No name was provided.')
}
}
})
router.navigate('users/') // logs `No name was provided.`
router.navigate('users/bob') // logs `'bob'`
Using *
will catch any routes that do not match previously defined routes. Use this as a catch all for any unexpected routes or for a 404:
router({
path: 'users/*',
action: function() {
console.log('Caught unexpected route!')
}
})
router.navigate('users/12312312')
You can block a route by returning false:
router({
path: '/admin',
action: function() {
return false
}
})
If you want to remove all current routes and handlers, you can invokde the following:
router.removeAll()
After running that none of the paths will work.
You can remove a singular route as follows:
// Handler to delete later:
const removableHandler = () => {
console.log('This handler is temporary and subject to removal.')
}
router(
{
path: '/',
action: () => console.log('You are home!')
},
{
path: '/',
action: () => removableHandler
}
)
// Sometime later we remove the named handler:
router.remove('/', removableHandler)