@t8/react-router

Route navigation

The route navigation API of @t8/react-router is largely aligned with the similar native APIs familiar to most web developers, such as <a href="/x"> and window.location, which helps reduce cognitive load and shorten the migration path from the native APIs:

+ import {A, useRoute} from '@t8/react-router';

  let UserNav = ({signedIn}) => {
+     let {route} = useRoute();

      let handleClick = () => {
-         window.location.assign(signedIn ? '/profile' : '/login');
+         route.assign(signedIn ? '/profile' : '/login');
      };

      return (
          <nav>
-             <a href="/">Home</a>
+             <A href="/">Home</A>
              <button onClick={handleClick}>Profile</button>
          </nav>
      );
  };

<A>

The route link component <A> enabling SPA navigation has the same props as the HTML link tag <a>. Apart from reducing some cognitive load, sticking to the similar API allows to quickly migrate from plain HTML links to route links (or the other way around).

import {A} from '@t8/react-router';

let Nav = () => (
    <nav>
        <A href="/intro">Intro</A>
    </nav>
);

<Area>

<Area>, the image map route link component, has the same props and semantics as the HTML image map tag <area>, with the SPA navigation enabled.

By setting data-navigation-mode="replace" on a route link component <A> or <Area>, it can be configured to replace the navigation history entry when clicked, which will prevent the user from returning to the previous location by pressing the browser's back button. By default, after a link component is clicked, the user can navigate back by pressing the browser's back button.

Imperative route navigation

To jump to another route programmatically, there's the route object returned from the useRoute() hook:

import {useRoute} from '@t8/react-router';

let ProfileButton = ({signedIn}) => {
    let {route} = useRoute();

    let handleClick = () => {
        route.assign(signedIn ? '/profile' : '/login');
    };

    return <button onClick={handleClick}>Profile</button>;
};

This particular example is somewhat contrived since it could have been composed in a declarative fashion using the route link component <A>. Still, it demonstrates how the route object can be used in use cases where the imperative navigation is the only reasonable way to go.

The interface of the route object consists of the following parts:

  • SPA navigation via the History API:
    • .assign(), .replace(), .reload(), .href, .pathname, .search, .hash, semantically similar to window.location;
    • .back(), .forward(), .go(delta), corresponding to the history methods;
  • route matching:
    • .match(pattern), accepting various types of location patterns (string | RegExp | (string | RegExp)[]) and returning an object containing the matched parameters and a flag indicating whether the current location matches the given pattern.