react-mini-router-hook
Version:
Mini Router for React using hooks
131 lines (99 loc) • 3.73 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var React__default = _interopDefault(React);
var Regexp = require('path-to-regexp');
function RouteBuild (routes) {
return function routeBuild (location, props) {
props = props || {};
var params = {};
for (var route in routes) {
var m = match(route, params, location);
var fn = routes[route];
if (m) {
if (typeof fn !== 'function') { return fn }
else { return fn(params, props) }
}
}
return null
}
}
function match(path, params, pathname) {
var keys = [];
var regexp = Regexp(path, keys);
var m = regexp.exec(pathname);
if (!m) { return false; }
else if (!params) { return true; }
for (var i = 1, len = m.length; i < len; ++i) {
var key = keys[i - 1];
var val = 'string' == typeof m[i] ? decodeURIComponent(m[i]) : m[i];
if (key) { params[key.name] = val; }
}
return true;
}
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
var routes = {};
function RouterRender(props) {
function addRoute(el, parent) {
var ref = el.props;
var path = ref.path;
var component = ref.component;
var children = ref.children;
var rest = objectWithoutProperties( ref, ["path", "component", "children"] );
var routeProps = rest;
var render = function (params, renderProps) {
var finalProps = Object.assign({}, props, routeProps, renderProps, {params: params});
var children = React.createElement(component, finalProps);
return parent ? parent.render(params, { children: children }) : children;
};
var route = normalizeRoute(path, parent).replace(/\/\//g, "/");
routes[route] = render;
if (children) { addRoutes(children, { route: route, render: render }); }
}
function addRoutes(routes, parent) {
React.Children.forEach(routes, function (r) { return addRoute(r, parent); });
}
addRoutes(props.children);
var router = RouteBuild(routes);
return router(props.location, { children: null });
}
var RouterContext = React__default.createContext({ path: undefined, setPath: function () { return null; } });
function Router(props) {
var ref = React.useState(props.location);
var path = ref[0];
var setState = ref[1];
function setPath(path, pathTitle, pathState){
if ( pathTitle === void 0 ) pathTitle='';
if ( pathState === void 0 ) pathState={};
window.history.pushState(pathState, pathTitle, path);
setState(path);
}
function updateOnBrowserButtons(){
if(window.location.pathname !== path){
setState(window.location.pathname);
}
}
React.useEffect(function () {
window.addEventListener('popstate', updateOnBrowserButtons);
return function () {
window.removeEventListener('popstate', updateOnBrowserButtons);
};
});
var contextState = { path: path, setPath: setPath };
return (
React__default.createElement( RouterContext.Provider, { value: contextState },
React__default.createElement( RouterRender, Object.assign({}, props, { location: path || props.location }))
)
);
}
function Route() {}
function normalizeRoute(path, parent) {
if (!path) { return parent ? parent.route : "/"; }
if (path[0] === "/") { return path; }
if (parent == null) { return path; }
return ((parent.route) + "/" + path);
}
exports.Route = Route;
exports.Router = Router;
exports.RouterContext = RouterContext;