Skip to content

Commit 7c129f5

Browse files
committed
Merge pull request #2383 from taion/custom-RoutingContext
[added] Support custom RoutingContext on Router
2 parents efac1a8 + ec3f3eb commit 7c129f5

File tree

2 files changed

+107
-2
lines changed

2 files changed

+107
-2
lines changed

modules/Router.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,18 @@ class Router extends Component {
1919
history: object,
2020
children: routes,
2121
routes, // alias for children
22+
RoutingContext: func.isRequired,
2223
createElement: func,
2324
onError: func,
2425
onUpdate: func,
2526
parseQueryString: func,
2627
stringifyQuery: func
2728
}
2829

30+
static defaultProps = {
31+
RoutingContext
32+
}
33+
2934
constructor(props, context) {
3035
super(props, context)
3136

@@ -80,12 +85,17 @@ class Router extends Component {
8085

8186
render() {
8287
let { location, routes, params, components } = this.state
83-
let { createElement } = this.props
88+
let { RoutingContext, createElement, ...props } = this.props
8489

8590
if (location == null)
8691
return null // Async match
8792

93+
// Only forward non-Router-specific props to routing context, as those are
94+
// the only ones that might be custom routing context props.
95+
Object.keys(Router.propTypes).forEach(propType => delete props[propType])
96+
8897
return React.createElement(RoutingContext, {
98+
...props,
8999
history: this.history,
90100
createElement,
91101
location,

modules/__tests__/Router-test.js

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import expect from 'expect'
22
import React, { Component } from 'react'
33
import { render, unmountComponentAtNode } from 'react-dom'
44
import createHistory from 'history/lib/createMemoryHistory'
5-
import Router from '../Router'
65
import Route from '../Route'
6+
import Router from '../Router'
7+
import RoutingContext from '../RoutingContext'
78

89
describe('Router', function () {
910

@@ -248,4 +249,98 @@ describe('Router', function () {
248249

249250
})
250251

252+
describe('RoutingContext', function () {
253+
it('applies custom RoutingContext', function (done) {
254+
const Parent = ({ children }) => <span>parent:{children}</span>
255+
const Child = () => <span>child</span>
256+
257+
class LabelWrapper extends Component {
258+
static defaultProps = {
259+
createElement: React.createElement
260+
}
261+
262+
createElement = (component, props) => {
263+
const { label, createElement } = this.props
264+
265+
return (
266+
<span>
267+
{label}-inner:{createElement(component, props)}
268+
</span>
269+
)
270+
}
271+
272+
render() {
273+
const { label, children } = this.props
274+
const child = React.cloneElement(children, {
275+
createElement: this.createElement
276+
})
277+
278+
return (
279+
<span>
280+
{label}-outer:{child}
281+
</span>
282+
)
283+
}
284+
}
285+
286+
const CustomRoutingContext = props => (
287+
<LabelWrapper label="m1">
288+
<LabelWrapper label="m2">
289+
<RoutingContext {...props} />
290+
</LabelWrapper>
291+
</LabelWrapper>
292+
)
293+
294+
render((
295+
<Router
296+
history={createHistory('/child')}
297+
RoutingContext={CustomRoutingContext}
298+
>
299+
<Route path="/" component={Parent}>
300+
<Route path="child" component={Child} />
301+
</Route>
302+
</Router>
303+
), node, function () {
304+
// Note that the nesting order is inverted for `createElement`, because
305+
// the order of function application is outermost-first.
306+
expect(node.textContent).toBe(
307+
'm1-outer:m2-outer:m2-inner:m1-inner:parent:m2-inner:m1-inner:child'
308+
)
309+
done()
310+
})
311+
})
312+
313+
it('passes router props to custom RoutingContext', function (done) {
314+
const MyComponent = () => <div />
315+
const route = { path: '/', component: MyComponent }
316+
317+
const Wrapper = (
318+
{ routes, components, foo, RoutingContext, children }
319+
) => {
320+
expect(routes).toEqual([ route ])
321+
expect(components).toEqual([ MyComponent ])
322+
expect(foo).toBe('bar')
323+
expect(RoutingContext).toNotExist()
324+
done()
325+
326+
return children
327+
}
328+
const CustomRoutingContext = props => (
329+
<Wrapper {...props}>
330+
<RoutingContext {...props} />
331+
</Wrapper>
332+
)
333+
334+
render((
335+
<Router
336+
history={createHistory('/')}
337+
routes={route}
338+
RoutingContext={CustomRoutingContext}
339+
foo="bar"
340+
/>
341+
), node)
342+
})
343+
344+
})
345+
251346
})

0 commit comments

Comments
 (0)