forked from remix-run/react-router
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRouterContext.js
More file actions
121 lines (98 loc) · 3.29 KB
/
RouterContext.js
File metadata and controls
121 lines (98 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import invariant from 'invariant'
import React from 'react'
import deprecateObjectProperties from './deprecateObjectProperties'
import getRouteParams from './getRouteParams'
import { isReactChildren } from './RouteUtils'
import warning from './routerWarning'
const { array, func, object } = React.PropTypes
/**
* A <RouterContext> renders the component tree for a given router state
* and sets the history object and the current location in context.
*/
const RouterContext = React.createClass({
propTypes: {
history: object,
router: object.isRequired,
location: object.isRequired,
routes: array.isRequired,
params: object.isRequired,
components: array.isRequired,
createElement: func.isRequired
},
getDefaultProps() {
return {
createElement: React.createElement
}
},
childContextTypes: {
history: object,
location: object.isRequired,
router: object.isRequired
},
getChildContext() {
let { router, history, location } = this.props
if (!router) {
warning(false, '`<RouterContext>` expects a `router` rather than a `history`')
router = {
...history,
setRouteLeaveHook: history.listenBeforeLeavingRoute
}
delete router.listenBeforeLeavingRoute
}
if (__DEV__) {
location = deprecateObjectProperties(location, '`context.location` is deprecated, please use a route component\'s `props.location` instead. http://tiny.cc/router-accessinglocation')
}
return { history, location, router }
},
createElement(component, props) {
return component == null ? null : this.props.createElement(component, props)
},
render() {
const { history, location, routes, params, components } = this.props
let element = null
if (components) {
element = components.reduceRight((element, components, index) => {
if (components == null)
return element // Don't create new children; use the grandchildren.
const route = routes[index]
const routeParams = getRouteParams(route, params)
const props = {
history,
location,
params,
route,
routeParams,
routes
}
if (isReactChildren(element)) {
props.children = element
} else if (element) {
for (const prop in element)
if (Object.prototype.hasOwnProperty.call(element, prop))
props[prop] = element[prop]
}
if (typeof components === 'object') {
const elements = {}
for (const key in components) {
if (Object.prototype.hasOwnProperty.call(components, key)) {
// Pass through the key as a prop to createElement to allow
// custom createElement functions to know which named component
// they're rendering, for e.g. matching up to fetched data.
elements[key] = this.createElement(components[key], {
key, ...props
})
}
}
return elements
}
return this.createElement(components, props)
}, element)
}
invariant(
element === null || element === false || React.isValidElement(element),
'The root route must render a single element'
)
return element
}
})
export default RouterContext