frint-router-react

npm

Router package for Frint


Guide

Installation

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>

Usage

This package exports a handful of components.

Route component

The Route component is how you define a route in your application, that can render either a Component or an App.

Components

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.

Apps

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 component

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 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.

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 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>
  );
}

Nested routes

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 prop

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.

Note

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.


API

Route

Route

Props

  1. path (String): The pattern to match against
  2. Example (plain): /about
  3. Example (with params): /about/:user
  4. exact (Boolean): Match the path exactly (with no suffix in the path)
  5. component (Component): The React component to render 1, render (Function): For rendering inline via wrapped stateless components
  6. app (App): Frint App that you want to render

Link

Props

  1. to (String): Path to navigate to
  2. type (String): If you want the Link to render as a <button> with its type, otherwise defaults to plain anchors (<a>)
  3. className (String): CSS class name
  4. activeClassName (String): CSS class name to render with, if current URL matches the Link's
  5. exact (Boolean): Trigger activeClassName by matching the path exactly
  6. children (Node): The body of the Link

Switch

Switch

Props

  1. children (Node): Children of <Route>s