diff --git a/modules/IndexRoute.js b/modules/IndexRoute.js new file mode 100644 index 0000000000..abcfff2e86 --- /dev/null +++ b/modules/IndexRoute.js @@ -0,0 +1,46 @@ +import React from 'react'; +import invariant from 'invariant'; +import { createRouteFromReactElement } from './RouteUtils'; +import { component, components, falsy } from './PropTypes'; + +var { bool, func } = React.PropTypes; + +/** + * An is used to specify its parent's in + * a JSX route config. + */ +var IndexRoute = React.createClass({ + + statics: { + + createRouteFromReactElement(element, parentRoute) { + if (parentRoute) { + parentRoute.indexRoute = createRouteFromReactElement(element); + } else { + warning( + false, + 'An does not make sense at the root of your route config' + ); + } + } + + }, + + propTypes: { + path: falsy, + ignoreScrollBehavior: bool, + component, + components, + getComponents: func + }, + + render() { + invariant( + false, + ' elements are for router configuration only and should not be rendered' + ); + } + +}); + +export default IndexRoute; diff --git a/modules/RouteUtils.js b/modules/RouteUtils.js index 4fe4652de5..9f95890e7b 100644 --- a/modules/RouteUtils.js +++ b/modules/RouteUtils.js @@ -22,15 +22,23 @@ function checkPropTypes(componentName, propTypes, props) { } } +function createRoute(defaultProps, props) { + return { ...defaultProps, ...props }; +} + export function createRouteFromReactElement(element) { var type = element.type; - var route = Object.assign({}, type.defaultProps, element.props); + var route = createRoute(type.defaultProps, element.props); if (type.propTypes) checkPropTypes(type.displayName || type.name, type.propTypes, route); if (route.children) { - route.childRoutes = createRoutesFromReactChildren(route.children); + var childRoutes = createRoutesFromReactChildren(route.children, route); + + if (childRoutes.length) + route.childRoutes = childRoutes; + delete route.children; } @@ -54,14 +62,17 @@ export function createRouteFromReactElement(element) { * Note: This method is automatically used when you provide children * to a component. */ -export function createRoutesFromReactChildren(children) { +export function createRoutesFromReactChildren(children, parentRoute) { var routes = []; React.Children.forEach(children, function (element) { if (React.isValidElement(element)) { // Component classes may have a static create* method. if (element.type.createRouteFromReactElement) { - routes.push(element.type.createRouteFromReactElement(element)); + var route = element.type.createRouteFromReactElement(element, parentRoute); + + if (route) + routes.push(route); } else { routes.push(createRouteFromReactElement(element)); } diff --git a/modules/__tests__/createRoutesFromReactChildren-test.js b/modules/__tests__/createRoutesFromReactChildren-test.js index 21d1d33ddd..af56cc08a2 100644 --- a/modules/__tests__/createRoutesFromReactChildren-test.js +++ b/modules/__tests__/createRoutesFromReactChildren-test.js @@ -1,6 +1,7 @@ import expect from 'expect'; import React from 'react'; import { createRoutesFromReactChildren } from '../RouteUtils'; +import IndexRoute from '../IndexRoute'; import Route from '../Route'; describe('createRoutesFromReactChildren', function () { @@ -28,10 +29,28 @@ describe('createRoutesFromReactChildren', function () { } }); + it('works with index routes', function () { + var routes = createRoutesFromReactChildren( + + + + ); + + expect(routes).toEqual([ + { + path: '/', + component: Parent, + indexRoute: { + component: Hello + } + } + ]); + }); + it('works with nested routes', function () { var routes = createRoutesFromReactChildren( - + ); @@ -50,9 +69,9 @@ describe('createRoutesFromReactChildren', function () { it('works with falsy children', function () { var routes = createRoutesFromReactChildren([ - , + , null, - , + , undefined ]); @@ -71,7 +90,7 @@ describe('createRoutesFromReactChildren', function () { var routes = createRoutesFromReactChildren( // This is a comment. - + ); diff --git a/modules/index.js b/modules/index.js index ceb42a4359..74a210bc27 100644 --- a/modules/index.js +++ b/modules/index.js @@ -3,6 +3,7 @@ export Router from './Router'; export Link from './Link'; /* components (configuration) */ +export IndexRoute from './IndexRoute'; export Redirect from './Redirect'; export Route from './Route';