Skip to content

Commit 282827e

Browse files
committed
Merge pull request #2855 from taion/onEnter-location-descriptor
Use location descriptor in onEnter redirect
2 parents e5bacaa + a6028e2 commit 282827e

File tree

9 files changed

+69
-39
lines changed

9 files changed

+69
-39
lines changed

docs/guides/basics/RouteConfiguration.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ const routeConfig = [
193193
childRoutes: [
194194
{ path: '/messages/:id', component: Message },
195195
{ path: 'messages/:id',
196-
onEnter: function (nextState, replaceState) {
197-
replaceState(null, '/messages/' + nextState.params.id)
196+
onEnter: function (nextState, replace) {
197+
replace('/messages/' + nextState.params.id)
198198
}
199199
}
200200
]

examples/auth-flow/app.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,13 @@ const Logout = React.createClass({
117117
}
118118
})
119119

120-
function requireAuth(nextState, replaceState) {
121-
if (!auth.loggedIn())
122-
replaceState({ nextPathname: nextState.location.pathname }, '/login')
120+
function requireAuth(nextState, replace) {
121+
if (!auth.loggedIn()) {
122+
replace({
123+
pathname: '/login',
124+
state: { nextPathname: nextState.location.pathname }
125+
})
126+
}
123127
}
124128

125129
render((

examples/auth-with-shared-root/config/routes.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import auth from '../utils/auth.js'
22

3-
function redirectToLogin(nextState, replaceState) {
3+
function redirectToLogin(nextState, replace) {
44
if (!auth.loggedIn()) {
5-
replaceState({
6-
nextPathname: nextState.location.pathname
7-
}, '/login')
5+
replace({
6+
pathname: '/login',
7+
state: { nextPathname: nextState.location.pathname }
8+
})
89
}
910
}
1011

11-
function redirectToDashboard(nextState, replaceState) {
12+
function redirectToDashboard(nextState, replace) {
1213
if (auth.loggedIn()) {
13-
replaceState(null, '/')
14+
replace('/')
1415
}
1516
}
1617

modules/Redirect.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const Redirect = React.createClass({
2323
if (route.from)
2424
route.path = route.from
2525

26-
route.onEnter = function (nextState, replaceState) {
26+
route.onEnter = function (nextState, replace) {
2727
const { location, params } = nextState
2828

2929
let pathname
@@ -38,11 +38,11 @@ const Redirect = React.createClass({
3838
pathname = formatPattern(pattern, params)
3939
}
4040

41-
replaceState(
42-
route.state || location.state,
41+
replace({
4342
pathname,
44-
route.query || location.query
45-
)
43+
query: route.query || location.query,
44+
state: route.state || location.state
45+
})
4646
}
4747

4848
return route

modules/TransitionUtils.js

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { loopAsync } from './AsyncUtils'
2+
import warning from './warning'
23

34
function createEnterHook(hook, route) {
45
return function (a, b, callback) {
@@ -23,9 +24,9 @@ function getEnterHooks(routes) {
2324

2425
/**
2526
* Runs all onEnter hooks in the given array of routes in order
26-
* with onEnter(nextState, replaceState, callback) and calls
27+
* with onEnter(nextState, replace, callback) and calls
2728
* callback(error, redirectInfo) when finished. The first hook
28-
* to use replaceState short-circuits the loop.
29+
* to use replace short-circuits the loop.
2930
*
3031
* If a hook needs to run asynchronously, it may use the callback
3132
* function. However, doing so will cause the transition to pause,
@@ -40,12 +41,26 @@ export function runEnterHooks(routes, nextState, callback) {
4041
}
4142

4243
let redirectInfo
43-
function replaceState(state, pathname, query) {
44-
redirectInfo = { pathname, query, state }
44+
function replace(location, deprecatedPathname, deprecatedQuery) {
45+
if (deprecatedPathname) {
46+
warning(
47+
false,
48+
'`replaceState(state, pathname, query) is deprecated; use `replace(location)` with a location descriptor instead. http://tiny.cc/router-isActivedeprecated'
49+
)
50+
redirectInfo = {
51+
pathname: deprecatedPathname,
52+
query: deprecatedQuery,
53+
state: location
54+
}
55+
56+
return
57+
}
58+
59+
redirectInfo = location
4560
}
4661

4762
loopAsync(hooks.length, function (index, next, done) {
48-
hooks[index](nextState, replaceState, function (error) {
63+
hooks[index](nextState, replace, function (error) {
4964
if (error || redirectInfo) {
5065
done(error, redirectInfo) // No need to continue.
5166
} else {

modules/__tests__/serverRendering-test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ describe('server rendering', function () {
5555

5656
const RedirectRoute = {
5757
path: '/company',
58-
onEnter(nextState, replaceState) {
59-
replaceState(null, '/about')
58+
onEnter(nextState, replace) {
59+
replace('/about')
6060
}
6161
}
6262

modules/__tests__/transitionHooks-test.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ describe('When a router enters a branch', function () {
5353
NewsFeedRoute = {
5454
path: 'news',
5555
component: NewsFeed,
56-
onEnter(nextState, replaceState) {
56+
onEnter(nextState, replace) {
5757
expect(this).toBe(NewsFeedRoute)
5858
expect(nextState.routes).toContain(NewsFeedRoute)
59-
expect(replaceState).toBeA('function')
59+
expect(replace).toBeA('function')
6060
},
6161
onLeave() {
6262
expect(this).toBe(NewsFeedRoute)
@@ -66,10 +66,10 @@ describe('When a router enters a branch', function () {
6666
InboxRoute = {
6767
path: 'inbox',
6868
component: Inbox,
69-
onEnter(nextState, replaceState) {
69+
onEnter(nextState, replace) {
7070
expect(this).toBe(InboxRoute)
7171
expect(nextState.routes).toContain(InboxRoute)
72-
expect(replaceState).toBeA('function')
72+
expect(replace).toBeA('function')
7373
},
7474
onLeave() {
7575
expect(this).toBe(InboxRoute)
@@ -78,12 +78,12 @@ describe('When a router enters a branch', function () {
7878

7979
RedirectToInboxRoute = {
8080
path: 'redirect-to-inbox',
81-
onEnter(nextState, replaceState) {
81+
onEnter(nextState, replace) {
8282
expect(this).toBe(RedirectToInboxRoute)
8383
expect(nextState.routes).toContain(RedirectToInboxRoute)
84-
expect(replaceState).toBeA('function')
84+
expect(replace).toBeA('function')
8585

86-
replaceState(null, '/inbox')
86+
replace('/inbox')
8787
},
8888
onLeave() {
8989
expect(this).toBe(RedirectToInboxRoute)
@@ -92,10 +92,10 @@ describe('When a router enters a branch', function () {
9292

9393
MessageRoute = {
9494
path: 'messages/:messageID',
95-
onEnter(nextState, replaceState) {
95+
onEnter(nextState, replace) {
9696
expect(this).toBe(MessageRoute)
9797
expect(nextState.routes).toContain(MessageRoute)
98-
expect(replaceState).toBeA('function')
98+
expect(replace).toBeA('function')
9999
},
100100
onLeave() {
101101
expect(this).toBe(MessageRoute)
@@ -105,10 +105,10 @@ describe('When a router enters a branch', function () {
105105
DashboardRoute = {
106106
path: '/',
107107
component: Dashboard,
108-
onEnter(nextState, replaceState) {
108+
onEnter(nextState, replace) {
109109
expect(this).toBe(DashboardRoute)
110110
expect(nextState.routes).toContain(DashboardRoute)
111-
expect(replaceState).toBeA('function')
111+
expect(replace).toBeA('function')
112112
},
113113
onLeave() {
114114
expect(this).toBe(DashboardRoute)

modules/createTransitionManager.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,8 @@ export default function createTransitionManager(history, routes) {
4545
)
4646
}
4747

48-
function createLocationFromRedirectInfo({ pathname, query, state }) {
49-
return history.createLocation(
50-
history.createPath(pathname, query), state, REPLACE
51-
)
48+
function createLocationFromRedirectInfo(location) {
49+
return history.createLocation(location, REPLACE)
5250
}
5351

5452
let partialNextState

upgrade-guides/v2.0.0.md

+13-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ const DeepComponent = React.createClass({
229229
}
230230
```
231231
232-
## `<Link to>` and `isActive` take location descriptors
232+
## `<Link to>`, `onEnter`, and `isActive` use location descriptors
233233
234234
`<Link to>` can now take a location descriptor in addition to strings. The `query` and `state` props are deprecated.
235235
@@ -244,6 +244,18 @@ const DeepComponent = React.createClass({
244244
<Link to="/foo"/>
245245
```
246246
247+
Likewise, redirecting from an `onEnter` hook now also uses a location descriptor.
248+
249+
```js
250+
// v1.0.x
251+
(nextState, replaceState) => replaceState(null, '/foo')
252+
(nextState, replaceState) => replaceState(null, '/foo', { the: 'query' })
253+
254+
// v2.0.0
255+
(nextState, replace) => replace('/foo')
256+
(nextState, replace) => replace({ pathname: '/foo', query: { the: 'query' } })
257+
```
258+
247259
For custom link-like components, the same applies for `router.isActive`, previously `history.isActive`.
248260
249261
```js

0 commit comments

Comments
 (0)