Skip to content

Commit

Permalink
Support fragments in makeRouteConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
taion committed Jul 28, 2018
1 parent c14c489 commit e7edf24
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 33 deletions.
84 changes: 51 additions & 33 deletions src/makeRouteConfig.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,60 @@
import React from 'react';

/**
* Create a route configuration from JSX configuration elements.
*/
export default function makeRouteConfig(node) {
return React.Children.toArray(node)
.filter(React.isValidElement)
.map(({ type: Type, props: { children, ...props } }) => {
if (__DEV__) {
if (Type.prototype.constructor !== Type) {
// Unwrap proxies from react-proxy. This isn't strictly necessary.
// eslint-disable-next-line no-param-reassign
Type = Type.prototype.constructor;
} else if (
// eslint-disable-next-line no-underscore-dangle
Type.__reactstandin__getCurrent
) {
// Unwrap proxies from react-stand-in.
// eslint-disable-next-line no-param-reassign
Type = Object.getPrototypeOf(Type);
}
function buildRouteConfig(node, routeConfig) {
React.Children.forEach(node, child => {
if (!React.isValidElement(child)) {
return;
}

let Type = child.type;
const { children, ...props } = child.props;

if (Type === React.Fragment) {
buildRouteConfig(children, routeConfig);
return;
}

if (__DEV__) {
if (Type.prototype.constructor !== Type) {
// Unwrap proxies from react-proxy. This isn't strictly necessary.
// eslint-disable-next-line no-param-reassign
Type = Type.prototype.constructor;
} else if (
// eslint-disable-next-line no-underscore-dangle
Type.__reactstandin__getCurrent
) {
// Unwrap proxies from react-stand-in.
// eslint-disable-next-line no-param-reassign
Type = Object.getPrototypeOf(Type);
}
}

const route = new Type(props);
const route = new Type(props);

if (children) {
if (React.isValidElement(children) || Array.isArray(children)) {
route.children = makeRouteConfig(children);
} else {
const routeGroups = {};
Object.entries(children).forEach(([groupName, groupRoutes]) => {
routeGroups[groupName] = makeRouteConfig(groupRoutes);
});
if (children) {
if (React.isValidElement(children) || Array.isArray(children)) {
// eslint-disable-next-line no-use-before-define
route.children = makeRouteConfig(children);
} else {
const routeGroups = {};
Object.entries(children).forEach(([groupName, groupRoutes]) => {
// eslint-disable-next-line no-use-before-define
routeGroups[groupName] = makeRouteConfig(groupRoutes);
});

route.children = routeGroups;
}
route.children = routeGroups;
}
}

return route;
});
routeConfig.push(route);
});

return routeConfig;
}

/**
* Create a route configuration from JSX configuration elements.
*/
export default function makeRouteConfig(node) {
return buildRouteConfig(node, []);
}
40 changes: 40 additions & 0 deletions test/makeRouteConfig.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe('makeRouteConfig', () => {
const MainPage = () => {};
const FooPage = () => {};
const BarPage = () => {};
const BazPage = () => {};

const FooNav = () => {};
const FooA = () => {};
Expand Down Expand Up @@ -60,6 +61,45 @@ describe('makeRouteConfig', () => {
]);
});

it('should work with fragments', () => {
expect(
makeRouteConfig(
<Route path="/" Component={AppPage}>
<Route Component={MainPage} />
<React.Fragment>
<Route path="foo" Component={FooPage} />
<React.Fragment>
<Route path="bar" Component={BarPage} />
</React.Fragment>
</React.Fragment>
<Route path="baz" Component={BazPage} />
</Route>,
),
).toEqual([
new Route({
path: '/',
Component: AppPage,
children: [
new Route({
Component: MainPage,
}),
new Route({
path: 'foo',
Component: FooPage,
}),
new Route({
path: 'bar',
Component: BarPage,
}),
new Route({
path: 'baz',
Component: BazPage,
}),
],
}),
]);
});

it('should work with <Redirect>', () => {
expect(
makeRouteConfig(
Expand Down

0 comments on commit e7edf24

Please sign in to comment.