Skip to content
This repository has been archived by the owner on Dec 15, 2018. It is now read-only.

How to specify custom matcher #255

Open
jkillian opened this issue Jan 23, 2018 · 2 comments
Open

How to specify custom matcher #255

jkillian opened this issue Jan 23, 2018 · 2 comments

Comments

@jkillian
Copy link

Hi redux-little-router team! One of the goals of the projects, which I appreciated, was:

Route matching should be simple and extendable.

Unfortunately, I'm having a lot of trouble figuring out how to override the matching behavior. Do you have an example of how I can provide a custom matcher to the router? Thanks!

I dove into the code some, and found that being able to supply this argument would likely do the trick - but I couldn't figure out anyway to supply it:

createMatcher = matcherFactory

@jkillian
Copy link
Author

jkillian commented Jan 23, 2018

As an additional note, I believe it might be possible to provide by plugging in to the createBrowserRouter function? But unfortunately that export isn't available in the latest released version yet:

export const createBrowserRouter = (installer: Function) =>

@jkillian
Copy link
Author

With the yet unreleased version, I believe code like this should work. The main change comes at the bottom of the code - I use the raw createBrowserRouter function and pass it a custom installer which simply calls the regular installer and supplies it with a custom matcher.

Obviously not a completely ergonomic API, but I'm happy it's possible!

import * as UrlPattern from 'url-pattern';
import { createBrowserRouter } from "@jkillian/redux-little-router/lib/environment/browser-router"
import install from "@jkillian/redux-little-router/lib/install"

type RouteCache = {
  route: string,
  pattern: UrlPattern,
  result: Object
};

const eagerMatcher = (routeList: Array<RouteCache>) =>
  (incomingUrl: string) => {
    // Discard query strings
    const pathname = incomingUrl.split('?')[0];

    // Find the route that matches the URL
    for (let i = 0; i < routeList.length; i++) {
      const storedRoute = routeList[i];
      const match = storedRoute.pattern.match(pathname);

      if (match) {
        // Return the matched params and user-defined result object
        return {
          route: storedRoute.route,
          params: match,
          result: storedRoute.result
        };
      }
    }

    return null;
  };

export const createMatcher = (routes: Object) => {
  const routeList = Object.keys(routes).sort().reverse().map(route => ({
    route,
    pattern: new UrlPattern(route, {segmentValueCharset: 'a-zA-Z0-9-_~ %@.'}),
    result: routes[route]
  }));

  return eagerMatcher(routeList);
};

export const createRouter = () => {
    return createBrowserRouter((opts) => install({...opts, createMatcher}));
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant