JSFiddle - React, Tailwind, and code Playground

by Alexander Maslakov

HTML

<ul>
  <li><a href="#" id="link1">userView</a></li>
  <li><a href="#" id="link2">authSignOut</a></li>
  <li><a href="#/not_found_in_routes_list">notFound</a></li>
</ul>
<div id="result"></div>

JavaScript

class Router {
	constructor (routes) {
  		this._routes = routes;
  }
  
  dispatch (uri) {
  	const normalizedUri = (uri ? uri: '/').replace(/^#/, '');
    const routes = this._routes;
    const routesNames = Object.keys(routes);
    for (let i=0; i<routesNames.length; i++) {
    	const routeName = routesNames[i];
    	const routePattern = routes[routeName];
      const normalizedRoutePattern = routePattern
      	.replace('\/', '\\/')
        .replace(/\:[^\/]+/, () => '([^\/]+)');
      const routeRegEx = new RegExp('^' + normalizedRoutePattern + '(?:\/|)$');
      let matches = null;
      if (matches = normalizedUri.match(routeRegEx)) {
      	const paramsHolders = routePattern.match(/\:([^\/]+)/g);
      	if (paramsHolders) {
        	const params = paramsHolders.reduce((accum, paramHolder, i) => {
          	accum[paramHolder.substring(1)] = matches[i + 1];
            return accum;
          }, {});
        	return {
          	uri: normalizedUri,
          	routeName,
            params
          };
        }
        return {
        	uri: normalizedUri,
        	routeName,
          params: null
        };
      }
    }
    return {
    	uri: normalizedUri,
      routeName: null,
      params: null
    };
  }
  
  uriFor (routeName, params={}) {
  	const routes = this._routes;
    const routePattern = routes[routeName];
    if (!routePattern) {
    	throw new Error(`Route with name '${routeName}' is not found.`);
    }
    const paramsHolders = routePattern.match(/\:([^\/]+)/g);
    if (!paramsHolders) {
    	return routePattern;
    }
    let uri = routePattern;
    for (let i=0; i<paramsHolders.length; i++) {
    	const holderName = paramsHolders[i].substring(1);
    	if (!params[holderName]) {
      	throw new Error(`Require param with name '${holderName}'.`);
      }
      uri = uri.replace(paramsHolders[i], params[holderName]);
    }
    return uri;
  }
}

function onHashChange (router, handler, dispatchImmediately=true)...