Move route util functions to a separate module

This commit is contained in:
Kimmo Puputti 2017-02-15 15:31:39 +02:00
parent 0b963a6332
commit d56a00a316
6 changed files with 81 additions and 79 deletions

View file

@ -8,7 +8,8 @@ import en from 'react-intl/locale-data/en';
import configureStore from './store';
import Routes from './Routes';
import { RoutesProvider } from './components';
import routesConfiguration, { flattenRoutes } from './routesConfiguration';
import routesConfiguration from './routesConfiguration';
import { flattenRoutes } from './util/routes';
import localeData from './translations/en.json';
export const ClientApp = props => {

View file

@ -5,7 +5,7 @@
*/
import React, { PropTypes } from 'react';
import { Link } from 'react-router-dom';
import { pathByRouteName } from '../../routesConfiguration';
import { pathByRouteName } from '../../util/routes';
const NamedLink = (props, context) => {
const { name, search, hash, state, params, ...rest } = props;

View file

@ -5,7 +5,7 @@
*/
import React, { PropTypes } from 'react';
import { Redirect } from 'react-router-dom';
import { pathByRouteName } from '../../routesConfiguration';
import { pathByRouteName } from '../../util/routes';
const NamedRedirect = (props, context) => {
const { name, search, state, params, ...rest } = props;

View file

@ -15,7 +15,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { ClientApp, renderApp } from './app';
import configureStore from './store';
import { matchPathname } from './routesConfiguration';
import { matchPathname } from './util/routes';
import rootSaga from './sagas';
import './index.css';

View file

@ -1,7 +1,4 @@
import React from 'react';
import { find } from 'lodash';
import { matchPath } from 'react-router-dom';
import pathToRegexp from 'path-to-regexp';
import { NamedRedirect } from './components';
import {
AuthenticationPage,
@ -261,76 +258,4 @@ const routesConfiguration = [
},
];
const flattenRoutes = routesArray =>
routesArray.reduce((a, b) => a.concat(b.routes ? [b].concat(flattenRoutes(b.routes)) : b), []);
const findRouteByName = (nameToFind, routes) => {
const flattenedRoutes = flattenRoutes(routes);
return find(flattenedRoutes, route => route.name === nameToFind);
};
/**
* E.g. ```const toListingPath = toPathByRouteName('ListingPage', routes);```
* Then we can generate listing paths with given params (```toListingPath({ id: uuidX })```)
*/
const toPathByRouteName = (nameToFind, routes) => {
const route = findRouteByName(nameToFind, routes);
if (!route) {
throw new Error(`Path "${nameToFind}" was not found.`);
}
return pathToRegexp.compile(route.path);
};
/**
* Shorthand for single path call. (```pathByRouteName('ListingPage', routes, { id: uuidX });```)
*/
const pathByRouteName = (nameToFind, routes, params = {}) =>
toPathByRouteName(nameToFind, routes)(params);
/**
* matchRoutesToLocation helps to figure out which routes are related to given location.
*/
const matchRoutesToLocation = (routes, location, matchedRoutes = [], params = {}) => {
let parameters = { ...params };
let matched = [...matchedRoutes];
routes.forEach(route => {
const { exact = false } = route;
const match = !route.path || matchPath(location.pathname, route.path, { exact });
if (match) {
matched.push(route);
if (match.params) {
parameters = { ...parameters, ...match.params };
}
}
if (route.routes) {
const { matchedRoutes: subRouteMatches, params: subRouteParams } = matchRoutesToLocation(
route.routes,
location,
matched,
parameters,
);
matched = matched.concat(subRouteMatches);
parameters = { ...parameters, ...subRouteParams };
}
});
return { matchedRoutes: matched, params: parameters };
};
const matchPathnameCreator = routes =>
(location, matchedRoutes = [], params = {}) =>
matchRoutesToLocation(routes, { pathname: location }, matchedRoutes, params);
/**
* matchRoutesToLocation helps to figure out which routes are related to given location.
*/
const matchPathname = matchPathnameCreator(routesConfiguration);
// Exported helpers
export { findRouteByName, flattenRoutes, matchPathname, toPathByRouteName, pathByRouteName };
export default routesConfiguration;

76
src/util/routes.js Normal file
View file

@ -0,0 +1,76 @@
import { find } from 'lodash';
import { matchPath } from 'react-router-dom';
import pathToRegexp from 'path-to-regexp';
import routesConfiguration from '../routesConfiguration';
const flattenRoutes = routesArray =>
routesArray.reduce((a, b) => a.concat(b.routes ? [b].concat(flattenRoutes(b.routes)) : b), []);
const findRouteByName = (nameToFind, routes) => {
const flattenedRoutes = flattenRoutes(routes);
return find(flattenedRoutes, route => route.name === nameToFind);
};
/**
* E.g. ```const toListingPath = toPathByRouteName('ListingPage', routes);```
* Then we can generate listing paths with given params (```toListingPath({ id: uuidX })```)
*/
const toPathByRouteName = (nameToFind, routes) => {
const route = findRouteByName(nameToFind, routes);
if (!route) {
throw new Error(`Path "${nameToFind}" was not found.`);
}
return pathToRegexp.compile(route.path);
};
/**
* Shorthand for single path call. (```pathByRouteName('ListingPage', routes, { id: uuidX });```)
*/
const pathByRouteName = (nameToFind, routes, params = {}) =>
toPathByRouteName(nameToFind, routes)(params);
/**
* matchRoutesToLocation helps to figure out which routes are related to given location.
*/
const matchRoutesToLocation = (routes, location, matchedRoutes = [], params = {}) => {
let parameters = { ...params };
let matched = [...matchedRoutes];
routes.forEach(route => {
const { exact = false } = route;
const match = !route.path || matchPath(location.pathname, route.path, { exact });
if (match) {
matched.push(route);
if (match.params) {
parameters = { ...parameters, ...match.params };
}
}
if (route.routes) {
const { matchedRoutes: subRouteMatches, params: subRouteParams } = matchRoutesToLocation(
route.routes,
location,
matched,
parameters,
);
matched = matched.concat(subRouteMatches);
parameters = { ...parameters, ...subRouteParams };
}
});
return { matchedRoutes: matched, params: parameters };
};
const matchPathnameCreator = routes =>
(location, matchedRoutes = [], params = {}) =>
matchRoutesToLocation(routes, { pathname: location }, matchedRoutes, params);
/**
* matchRoutesToLocation helps to figure out which routes are related to given location.
*/
const matchPathname = matchPathnameCreator(routesConfiguration);
// Exported helpers
export { findRouteByName, flattenRoutes, matchPathname, toPathByRouteName, pathByRouteName };