Skip to content

Commit 5dd12cd

Browse files
committed
Merge pull request #2647 from rackt/1.1-context.router
1.1 context.router
2 parents d885792 + 4ef698d commit 5dd12cd

9 files changed

+369
-9
lines changed

Diff for: .eslintrc

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
{
22
"extends": "rackt",
3+
"globals": {
4+
"__DEV__": true
5+
},
36
"rules": {
47
"react/jsx-uses-react": 1,
58
"react/jsx-no-undef": 2,

Diff for: CHANGES.md

+194
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,199 @@
11
## [HEAD]
22

3+
### Changes to context exports and Mixins
4+
5+
Only an object named `router` is added to context. Accessing `context.history`, `context.location`, and `context.route` are all deprecated.
6+
7+
Additionally, since `context` is now documented, all mixins are deprecated.
8+
9+
#### Accessing location
10+
11+
Access `location` from `this.props.location` of your route component. If
12+
you'd like to get it deeper in the tree, you can use whatever
13+
conventions your app has for getting props from high down low. One
14+
option is to put it context yourself:
15+
16+
```js
17+
// v1.0.x
18+
const RouteComponent = React.createClass({
19+
childContextTypes: {
20+
location: React.PropTypes.object
21+
},
22+
23+
getChildContext() {
24+
return { location: this.props.location }
25+
}
26+
})
27+
```
28+
29+
Though you may want to hide that in a mixin or higher order component,
30+
it's up to you.
31+
32+
#### Navigating
33+
34+
In all cases where you once had a `history` for navigation, you now have a `router` to navigate instead.
35+
36+
```js
37+
// v1.0.0
38+
history.pushState(state, path, query)
39+
history.replaceState(state, path, query)
40+
41+
// v1.1.0
42+
router.push(path)
43+
router.push({ path, query, state }) // new "location descriptor"
44+
45+
router.replace(path)
46+
router.replace({ path, query, state }) // new "location descriptor"
47+
```
48+
49+
#### Navigating in route components
50+
51+
```js
52+
// v1.0.0
53+
class RouteComponent extends React.Component {
54+
someHandler() {
55+
this.props.history.pushState(...)
56+
}
57+
}
58+
59+
// v1.1.0
60+
class RouteComponent extends React.Component {
61+
someHandler() {
62+
this.props.router.push(...)
63+
}
64+
}
65+
```
66+
67+
#### Navigating inside deeply nested components
68+
69+
```js
70+
// v1.0.0
71+
const DeepComponent = React.createClass({
72+
mixins: [ History ],
73+
74+
someHandler() {
75+
this.history.pushState(...)
76+
}
77+
}
78+
79+
// v1.1.0
80+
// You have a couple options:
81+
// Use context directly (recommended)
82+
const DeepComponent = React.createClass({
83+
contextTypes: {
84+
router: object.isRequired
85+
},
86+
87+
someHandler() {
88+
this.context.router.push(...)
89+
}
90+
}
91+
92+
// create your own mixin:
93+
const RouterMixin = {
94+
contextTypes: {
95+
router: object.isRequired
96+
},
97+
componentWillMount() {
98+
this.router = this.context.router
99+
}
100+
}
101+
102+
const DeepComponent = React.createClass({
103+
mixins: [ RouterMixin ],
104+
someHandler() {
105+
this.history.pushState(...)
106+
}
107+
}
108+
109+
// use the singleton history you are using when the router was rendered,
110+
import { browserHistory } from 'react-router'
111+
112+
const DeepComponent = React.createClass({
113+
someHandler() {
114+
browserHistory.push(...)
115+
}
116+
}
117+
```
118+
119+
#### Lifecycle Mixin with route components
120+
121+
```js
122+
// v1.0.0
123+
const RouteComponent = React.createClass({
124+
mixins: [ Lifecycle ],
125+
routerWillLeave() {
126+
// ...
127+
}
128+
})
129+
130+
// v1.1.0
131+
const RouteComponent = React.createClass({
132+
componentDidMount() {
133+
const { router, route } = this.props
134+
router.addRouteLeaveHook(route, this.routerWillLeave)
135+
}
136+
})
137+
138+
// or make your own mixin, check it out in the next section
139+
```
140+
141+
#### Lifecycle Mixin with deep, non-route components
142+
143+
```js
144+
// v1.0.0
145+
const DeepComponent = React.createClass({
146+
mixins: [ Lifecycle ],
147+
routerWillLeave() {
148+
// do stuff
149+
}
150+
})
151+
152+
// v1.1.0
153+
// you have a couple of options
154+
// first you can put the route on context in the route component
155+
const RouteComponent = React.createClass({
156+
childContextTypes: {
157+
route: object
158+
},
159+
160+
getChildContext() {
161+
return { route: this.props.route }
162+
}
163+
})
164+
165+
// and then access it on your deep component
166+
const DeepComponent = React.createClass({
167+
contextTypes: {
168+
route: object.isRequired,
169+
router: objec.isRequired
170+
},
171+
172+
componentDidMount() {
173+
const { router, route } = this.context
174+
router.addRouteLeaveHook(route, this.routerWillLeave)
175+
}
176+
})
177+
178+
// or make your own mixin that will work for both route components and
179+
// deep components alike (as long as your route component puts `route`
180+
// on context
181+
const Lifecycle = {
182+
contextTypes: {
183+
route: object.isRequired,
184+
router: objec.isRequired
185+
},
186+
187+
componentDidMount() {
188+
const router = this.context.router
189+
const route = this.props.route || this.context.route
190+
router.addRouteLeaveHook(route, this.routerWillLeave)
191+
}
192+
}
193+
```
194+
195+
196+
3197
## [v1.0.1]
4198
> Dec 5, 2015
5199

Diff for: docs/API.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
- [Named Components](#named-components)
1818

1919
* [Mixins](#mixins)
20-
- [Lifecycle](#lifecycle-mixin)
21-
- [History](#history-mixin)
22-
- [RouteContext](#routecontext-mixin)
20+
- [Lifecycle](#lifecycle-mixin) (Deprecated)
21+
- [History](#history-mixin) (Deprecated)
22+
- [RouteContext](#routecontext-mixin) (Deprecated)
2323

2424
* [Utilities](#utilities)
2525
* [useRoutes](#useroutescreatehistory)

Diff for: modules/History.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warning from 'warning'
12
import { history } from './PropTypes'
23

34
/**
@@ -10,6 +11,7 @@ const History = {
1011
},
1112

1213
componentWillMount() {
14+
warning(false, 'the `History` mixin is deprecated, please access `context.router` with your own `contextTypes` or see https://github.com/rackt/react-router/blob/v1.1.0/CHANGES.md#v110 for more options')
1315
this.history = this.context.history
1416
}
1517

Diff for: modules/Lifecycle.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warning from 'warning'
12
import React from 'react'
23
import invariant from 'invariant'
34

@@ -34,6 +35,7 @@ const Lifecycle = {
3435
},
3536

3637
componentDidMount() {
38+
warning(false, 'the `Lifcycle` mixin is deprecated, please use `this.props.router.addRouteLeaveHook(this.props.route, hook)` from a route component, see https://github.com/rackt/react-router/blob/v1.1.0/CHANGES.md#v110 for more details.')
3739
invariant(
3840
this.routerWillLeave,
3941
'The Lifecycle mixin requires you to define a routerWillLeave method'

Diff for: modules/RouteContext.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warning from 'warning'
12
import React from 'react'
23

34
const { object } = React.PropTypes
@@ -22,6 +23,10 @@ const RouteContext = {
2223
return {
2324
route: this.props.route
2425
}
26+
},
27+
28+
componentWillMount() {
29+
warning(false, 'the `RouteContext` mixin is deprecated, please export `this.props.route` from a route component yourself. See https://github.com/rackt/react-router/blob/v1.1.0/CHANGES.md#v110 for more details.')
2530
}
2631

2732
}

Diff for: modules/RoutingContext.js

+25-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,37 @@
1+
import deprecateObjectProperties from './deprecateObjectProperties'
12
import invariant from 'invariant'
23
import React, { Component } from 'react'
34
import { isReactChildren } from './RouteUtils'
45
import getRouteParams from './getRouteParams'
56

67
const { array, func, object } = React.PropTypes
78

8-
/**
9-
* A <RoutingContext> renders the component tree for a given router state
10-
* and sets the history object and the current location in context.
11-
*/
129
class RoutingContext extends Component {
1310

1411
getChildContext() {
1512
const { history, location } = this.props
16-
return { history, location }
13+
const router = {
14+
push(...args) {
15+
history.push(...args)
16+
},
17+
replace(...args) {
18+
history.replace(...args)
19+
},
20+
addRouteLeaveHook(...args) {
21+
return history.listenBeforeLeavingRoute(...args)
22+
},
23+
isActive(...args) {
24+
return history.isActive(...args)
25+
}
26+
}
27+
const contextExport = { history, location, router }
28+
if (__DEV__)
29+
return deprecateObjectProperties(contextExport, {
30+
history: '`context.history` is deprecated, please use context.router',
31+
location: '`context.location` is deprecated, please use a route component\'s `props.location` instead. If this is a deeply nested component, please refer to the strategies described in https://github.com/rackt/react-router/blob/v1.1.0/CHANGES.md#v110'
32+
})
33+
else
34+
return contextExport
1735
}
1836

1937
createElement(component, props) {
@@ -94,7 +112,8 @@ RoutingContext.defaultProps = {
94112

95113
RoutingContext.childContextTypes = {
96114
history: object.isRequired,
97-
location: object.isRequired
115+
location: object.isRequired,
116+
router: object.isRequired
98117
}
99118

100119
export default RoutingContext

0 commit comments

Comments
 (0)