Router package for Frint
With npm:
$ npm install --save frint-router frint-router-preact
Via unpkg CDN:
<script src="https://unpkg.com/frint-router-preact@latest/dist/frint-router-preact.min.js"></script>
<script>
// available as `window.FrintRouterPreact`
</script>
This package exports a handful of components.
The Route
component is how you define a route in your application, that can render either a Component or an App.
Assume you have two components HomePage
and AboutPage
, and you want to show them when the browser navigates to /
and /about
respectively:
// components/Root.js
import { h } from 'preact';
import { Route } from 'frint-router-preact';
import HomePage from './HomePage';
import AboutPage from './AboutPage';
export default function Root() {
return (
<div>
<Route path="/" component={HomePage} exact />
<Route path="/about" component={AboutPage} />
</div>
);
}
The exact
prop means, the route will be matched to the exact string /
. Any further suffix in the URL would result in a no match.
Similar to Components, Apps can also be mounted for specific routes:
// components/Root.js
import { h } from 'preact';
import { Route } from 'frint-router-preact';
import HomePage from './HomePage';
import ContactPageApp from '../contactPageApp';
export default function Root() {
return (
<div>
<Route path="/about" app={ContactPage} />
</div>
);
}
(This component is not fully ported yet from frint-react
, and needs more work)
The Switch
component makes sure only one direct child Route
is shown. The first one to match always wins, and the last Route
with no path
is rendered as a default case.
Take a look at this scenario, for e.g.:
// components/MyComponent.js
import { h } from 'preact';
import { Switch, Route } from 'frint-router-preact';
import Foo from './Foo';
import Bar from './Bar';
import Baz from './Baz';
function NoMatch() {
return (
<p>Nothing to show.</p>
);
}
export default MyComponent() {
return (
<div>
<Switch>
<Route path="/foo" component={Foo} />
<Route path="/bar" component={Bar} />
<Route path="/baz" component={Baz} />
<Route component={NoMatch} />
</Switch>
</div>
);
}
If the URL happens to be /foo
, then Foo
component will render. Same follows for Bar
and Baz
if URLs are /bar
and /baz
respectively.
And only one of them can render at the same time. If there is no match, the last Route
with no path
defined will be rendered. Much like handling the default
use case in a plain switch
statement in JavaScript.
The Link
component is used for creating links, that can navigate to other pages. It will take care of adapting to the router service that you are using from frint-router
automatically.
// components/TopNav.js
import { h } from 'preact';
import { Link } from 'frint-router-preact';
export default function TopNav() {
return (
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
);
}
You can also pass additional props to render the links with CSS class names when they are active for example:
export default function TopNav() {
return (
<ul>
<li>
<Link
to="/"
className="nav-link"
activeClassName="is-active"
exact
>
Home
</Link>
</li>
<li>
<Link
to="/about"
className="nav-link"
activeClassName="is-active"
>
About
</Link>
</li>
</ul>
);
}
When Route
renders a particular Component, the component is given a match
prop which contains information about the currently matched path.
If you had a route for /about
like this:
// components/Root.js
import { h } from 'preact';
import { Route } from 'frint-router-preact';
import HomePage from './HomePage';
import AboutPage from './AboutPage';
export default function Root() {
return (
<div>
<Route path="/" component={HomePage} exact />
<Route path="/about" component={AboutPage} />
</div>
);
}
And when you navigate to /about
in the browser, the AboutPage
component will have access to a match
prop:
// components/AboutPage.js
import { h } from 'preact';
export default function AboutPage(props) {
return (
<div>
<h2>About Page</h2>
<p>The current matched URL is {props.match.url}</p>
</div>
);
}
The page will render with the text The current matched URL is /about
.
Now that you know in which path the component rendered itself in, you can have further child routes in the Component:
// components/AboutPage.js
import { h } from 'preact';
import { Route, Switch } from 'frint-router-preact';
function NoMatch() {
return (
<p>No user has been selected.</p>
);
}
function ShowUser(props) {
const { match } = props;
return (
<p>Current selected user is {match.params.user}</p>
);
}
export default function AboutPage(props) {
const { match } = props;
return (
<div>
<h2>About Page</h2>
<ul>
<li><Link to={`${match.url}/harry`}>Harry</Link></li>
<li><Link to={`${match.url}/hermione`}>Hermione</Link></li>
<li><Link to={`${match.url}/ron`}>Ron</Link></li>
</ul>
<Switch>
<Route path={`${match.url}/:user`} component={ShowUser} />
<Route component={NoMatch} />
</Switch>
</div>
);
}
The props.match
object in Components follow a structure like this:
// in AboutPage component
{
url: '/about',
isExact: true,
params: {}
}
// in ShowUser component
{
url: '/about/hermione',
isExact: true,
params: {
user: 'hermione',
}
}
Since props.match
always contains the currenly matched URL info for the rendered Component, it is possible for you to create more child Routes dynamically.
This package is a close implementation of the APIs introduced by the awesome react-router
, but done in a way to fit well with rest of the FrintJS packages.
Route
path
(String
): The pattern to match against
- Example (plain):
/about
- Example (with params):
/about/:user
exact
(Boolean
): Match thepath
exactly (with no suffix in the path)component
(Component
): The React component to render 1,render
(Function
): For rendering inline via wrapped stateless componentsapp
(App
): Frint App that you want to render
Link
to
(String
): Path to navigate totype
(String
): If you want the Link to render as a<button>
with its type, otherwise defaults to plain anchors (<a>
)className
(String
): CSS class nameactiveClassName
(String
): CSS class name to render with, if current URL matches the Link'sexact
(Boolean
): TriggeractiveClassName
by matching the path exactlychildren
(Node
): The body of the Link
Switch
Now fully done yet.
children
(Node
): Children of<Route>
s