Router package for Frint
With npm:
$ npm install --save frint-router frint-router-react
Via unpkg CDN:
<script src="https://unpkg.com/frint-router-react@latest/dist/frint-router-react.min.js"></script>
<script>
// available as `window.FrintRouterReact`
</script>
This package exports a handful of components.
Route componentThe 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 { Route } from 'frint-router-react';
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 React from 'react';
import { Route } from 'frint-router-react';
import HomePage from './HomePage';
import ContactPageApp from '../contactPageApp';
export default function Root() {
return (
<div>
<Route path="/about" app={ContactPage} />
</div>
);
}
Switch componentThe 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 React from 'react';
import { Switch, Route } from 'frint-router-react';
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.
Link componentThe 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 React from 'react';
import { Link } from 'frint-router-react';
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 React from 'react';
import { Route } from 'frint-router-react';
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 React from 'react';
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 React from 'react';
import { Route, Switch } from 'frint-router-react';
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>
);
}
match propThe 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/about/about/:userexact (Boolean): Match the path 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 renderLink
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): Trigger activeClassName by matching the path exactlychildren (Node): The body of the LinkSwitch
children (Node): Children of <Route>s