diff --git a/src/index.js b/src/index.js index 967ec6af..9cf43ffe 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,7 @@ import createStoreWithRouter, { import provideRouter, { RouterProvider } from './provider'; import { Link, PersistentQueryLink } from './link'; import { AbsoluteFragment, RelativeFragment } from './fragment'; +import PlaceholderFragment from './placeholder-fragment'; import routerReducer from './reducer'; import createMatcher from './create-matcher'; @@ -35,6 +36,7 @@ export { Fragment, AbsoluteFragment, RelativeFragment, + PlaceholderFragment, // Public action types LOCATION_CHANGED, diff --git a/src/placeholder-fragment.js b/src/placeholder-fragment.js new file mode 100644 index 00000000..1836700d --- /dev/null +++ b/src/placeholder-fragment.js @@ -0,0 +1,77 @@ +// @flow +import type { Location } from 'history'; +import type { RouterContext } from './provider'; +import React, { PropTypes } from 'react'; + +type Props = { + forRoute?: string, + forRoutes?: Array, + withConditions?: (location: Location) => bool, + children: React.Element<*>, + componentKey: string, + componentPropsKey?: string +}; + +type Context = { + router?: RouterContext +}; + +const PlaceholderFragment = (props: Props, context: Context ) => { + const { + forRoute, + forRoutes, + withConditions, + children, + componentKey = 'component', + componentPropsKey = 'componentProps' + } = props; + + const { store } = context.router; + const { matchRoute } = store; + const { router: location } = store.getState(); + + const matchResult = matchRoute(location.pathname); + + if (!matchResult) { + return null; + } + + if ( + forRoute && + matchResult.route !== forRoute + ) { + return null; + } + + if (Array.isArray(forRoutes)) { + const anyMatch = forRoutes.some(route => + matchResult.route === route + ); + + if (!anyMatch) { + return null; + } + } + + if (withConditions && !withConditions(location)) { + return null; + } + + if (matchResult && matchResult.result && matchResult.result.hasOwnProperty(componentKey)) { + return React.createElement( + matchResult.result[componentKey], + matchResult.result.hasOwnProperty(componentPropsKey) ? + matchResult.result[componentPropsKey] : + {}, + children + ); + } + + return null; +}; + +PlaceholderFragment.contextTypes = { + router: PropTypes.object +}; + +export default PlaceholderFragment;