Skip to content

Commit f9f5a88

Browse files
taiontimdorr
authored andcommitted
Fix remaining issues with #3556 (#3561)
1 parent c1167fb commit f9f5a88

File tree

8 files changed

+159
-151
lines changed

8 files changed

+159
-151
lines changed

docs/API.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ A function used to convert an object from [`<Link>`](#link)s or calls to
8585
A function used to convert a query string into an object that gets passed to route component props.
8686

8787
##### `onError(error)`
88-
While the router is matching, errors may bubble up, here is your opportunity to catch and deal with them. Typically these will come from async features like [`route.getComponents`](#getcomponentsnextstate-callback), [`route.getIndexRoute`](#getindexroutelocation-callback), and [`route.getChildRoutes`](#getchildroutespartialnextstate-callback).
88+
While the router is matching, errors may bubble up, here is your opportunity to catch and deal with them. Typically these will come from async features like [`route.getComponents`](#getcomponentsnextstate-callback), [`route.getIndexRoute`](#getindexroutepartialnextstate-callback), and [`route.getChildRoutes`](#getchildroutespartialnextstate-callback).
8989

9090
##### `onUpdate()`
9191
Called whenever the router updates its state in response to URL changes.
@@ -317,8 +317,7 @@ class Users extends React.Component {
317317
```
318318

319319
##### `getComponent(nextState, callback)`
320-
Same as `component` but asynchronous, useful for
321-
code-splitting.
320+
Same as `component` but asynchronous, useful for code-splitting.
322321

323322
###### `callback` signature
324323
`cb(err, component)`
@@ -369,7 +368,7 @@ A plain JavaScript object route definition. `<Router>` turns JSX `<Route>`s into
369368
An array of child routes, same as `children` in JSX route configs.
370369

371370
##### `getChildRoutes(partialNextState, callback)`
372-
Same as `childRoutes` but asynchronous and receives the `partialNextState`. Useful for code-splitting and dynamic route matching (given some state or session data to return a different set of child routes).
371+
Same as `childRoutes` but asynchronous and receives `partialNextState`. Useful for code-splitting and dynamic route matching (given some state or session data to return a different set of child routes).
373372

374373
###### `callback` signature
375374
`cb(err, routesArray)`
@@ -414,9 +413,9 @@ let myRoute = {
414413
##### `indexRoute`
415414
The [index route](/docs/guides/IndexRoutes.md). This is the same as specifying an `<IndexRoute>` child when using JSX route configs.
416415

417-
##### `getIndexRoute(location, callback)`
416+
##### `getIndexRoute(partialNextState, callback)`
418417

419-
Same as `indexRoute`, but asynchronous and receives the `location`. As with `getChildRoutes`, this can be useful for code-splitting and dynamic route matching.
418+
Same as `indexRoute`, but asynchronous and receives `partialNextState`. As with `getChildRoutes`, this can be useful for code-splitting and dynamic route matching.
420419

421420
###### `callback` signature
422421
`cb(err, route)`
@@ -435,7 +434,7 @@ let myRoute = {
435434
// async index route
436435
let myRoute = {
437436
path: 'courses',
438-
getIndexRoute(location, cb) {
437+
getIndexRoute(partialNextState, cb) {
439438
// do something async here
440439
cb(null, myIndexRoute)
441440
}

docs/guides/DynamicRouting.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ A router is the perfect place to handle code splitting: it's responsible for set
1010

1111
React Router does all of its [path matching](/docs/guides/RouteMatching.md) and component fetching asynchronously, which allows you to not only load up the components lazily, *but also lazily load the route configuration*. You really only need one route definition in your initial bundle, the router can resolve the rest on demand.
1212

13-
Routes may define [`getChildRoutes`](/docs/API.md#getchildroutespartialnextstate-callback), [`getIndexRoute`](/docs/API.md#getindexroutelocation-callback), and [`getComponents`](/docs/API.md#getcomponentsnextstate-callback) methods. These are asynchronous and only called when needed. We call it "gradual matching". React Router will gradually match the URL and fetch only the amount of route configuration and components it needs to match the URL and render.
13+
Routes may define [`getChildRoutes`](/docs/API.md#getchildroutespartialnextstate-callback), [`getIndexRoute`](/docs/API.md#getindexroutepartialnextstate-callback), and [`getComponents`](/docs/API.md#getcomponentsnextstate-callback) methods. These are asynchronous and only called when needed. We call it "gradual matching". React Router will gradually match the URL and fetch only the amount of route configuration and components it needs to match the URL and render.
1414

1515
Coupled with a smart code splitting tool like [webpack](http://webpack.github.io/), a once tiresome architecture is now simple and declarative.
1616

@@ -28,7 +28,7 @@ const CourseRoute = {
2828
})
2929
},
3030

31-
getIndexRoute(location, callback) {
31+
getIndexRoute(partialNextState, callback) {
3232
require.ensure([], function (require) {
3333
callback(null, {
3434
component: require('./components/Index'),

modules/__tests__/isActive-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ describe('isActive', function () {
628628
childRoutes: [
629629
{ path: 'foo' }
630630
],
631-
getIndexRoute(location, callback) {
631+
getIndexRoute(partialNextState, callback) {
632632
setTimeout(() => callback(null, {}))
633633
}
634634
}

modules/__tests__/matchRoutes-test.js

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -291,67 +291,70 @@ describe('matchRoutes', function () {
291291
})
292292

293293
describe('an asynchronous JSX route config', function () {
294-
let getChildRoutes, getIndexRoute, jsxRoutes, makeJsxNestedRoutes
294+
let getChildRoutes, getIndexRoute, jsxRoutes
295295

296296
beforeEach(function () {
297-
getChildRoutes = function (partialNextState, callback) {
298-
setTimeout(function () {
299-
callback(null, <Route path=":userID" />)
300-
})
301-
}
297+
getChildRoutes = expect.createSpy().andCall(
298+
function (partialNextState, callback) {
299+
setTimeout(function () {
300+
callback(null, <Route path=":userId" />)
301+
})
302+
}
303+
)
302304

303-
getIndexRoute = function (location, callback) {
304-
setTimeout(function () {
305-
callback(null, <Route name="jsx" />)
306-
})
307-
}
305+
getIndexRoute = expect.createSpy().andCall(
306+
function (location, callback) {
307+
setTimeout(function () {
308+
callback(null, <Route name="jsx" />)
309+
})
310+
}
311+
)
308312

309313
jsxRoutes = createRoutes([
310-
<Route name="users"
311-
path="users"
312-
getChildRoutes={getChildRoutes}
313-
getIndexRoute={getIndexRoute} />
314+
<Route
315+
name="users"
316+
path=":groupId/users"
317+
getChildRoutes={getChildRoutes}
318+
getIndexRoute={getIndexRoute}
319+
/>
314320
])
315-
316-
makeJsxNestedRoutes = () => {
317-
const spy = expect.spyOn({ getChildRoutes }, 'getChildRoutes').andCallThrough()
318-
const routes = createRoutes([
319-
<Route name="users"
320-
path="users/:id">
321-
<Route name="topic"
322-
path=":topic"
323-
getChildRoutes={spy} />
324-
</Route>
325-
])
326-
return { spy, routes }
327-
}
328321
})
329322

330323
it('when getChildRoutes callback returns reactElements', function (done) {
331-
matchRoutes(jsxRoutes, createLocation('/users/5'), function (error, match) {
332-
expect(match).toExist()
333-
expect(match.routes.map(r => r.path)).toEqual([ 'users', ':userID' ])
334-
expect(match.params).toEqual({ userID: '5' })
335-
done()
336-
})
324+
matchRoutes(
325+
jsxRoutes, createLocation('/foo/users/5'),
326+
function (error, match) {
327+
expect(match).toExist()
328+
expect(match.routes.map(r => r.path)).toEqual([
329+
':groupId/users', ':userId'
330+
])
331+
expect(match.params).toEqual({ groupId: 'foo', userId: '5' })
332+
333+
expect(getChildRoutes.calls[0].arguments[0].params).toEqual({
334+
groupId: 'foo'
335+
})
336+
expect(getIndexRoute).toNotHaveBeenCalled()
337+
338+
done()
339+
}
340+
)
337341
})
338342

339343
it('when getIndexRoute callback returns reactElements', function (done) {
340-
matchRoutes(jsxRoutes, createLocation('/users'), function (error, match) {
341-
expect(match).toExist()
342-
expect(match.routes.map(r => r.name)).toEqual([ 'users', 'jsx' ])
343-
done()
344-
})
345-
})
346-
347-
it('when getChildRoutes callback returns partialNextState', function (done) {
348-
const jsxNestedRoutes = makeJsxNestedRoutes()
349-
matchRoutes(jsxNestedRoutes.routes, createLocation('/users/5/details/others'), function () {
350-
const state = jsxNestedRoutes.spy.calls[0].arguments[0]
351-
expect(state).toExist()
352-
expect(state.params).toEqual({ id: '5', topic: 'details' })
353-
done()
354-
})
344+
matchRoutes(
345+
jsxRoutes, createLocation('/bar/users'),
346+
function (error, match) {
347+
expect(match).toExist()
348+
expect(match.routes.map(r => r.name)).toEqual([ 'users', 'jsx' ])
349+
350+
expect(getIndexRoute.calls[0].arguments[0].params).toEqual({
351+
groupId: 'bar'
352+
})
353+
expect(getChildRoutes).toNotHaveBeenCalled()
354+
355+
done()
356+
}
357+
)
355358
})
356359
})
357360

modules/deprecateLocationProperties.js

Lines changed: 0 additions & 31 deletions
This file was deleted.

modules/getComponents.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { mapAsync } from './AsyncUtils'
2-
import { canUseMembrane } from './deprecateObjectProperties'
3-
import deprecateLocationProperties from './deprecateLocationProperties'
2+
import makeStateWithLocation from './makeStateWithLocation'
43

54
function getComponentsForRoute(nextState, route, callback) {
65
if (route.component || route.components) {
@@ -15,13 +14,7 @@ function getComponentsForRoute(nextState, route, callback) {
1514
}
1615

1716
const { location } = nextState
18-
let nextStateWithLocation
19-
20-
if (__DEV__ && canUseMembrane) {
21-
nextStateWithLocation = deprecateLocationProperties(nextState, location)
22-
} else {
23-
nextStateWithLocation = { ...nextState, ...location }
24-
}
17+
const nextStateWithLocation = makeStateWithLocation(nextState, location)
2518

2619
getComponent.call(route, nextStateWithLocation, callback)
2720
}

modules/makeStateWithLocation.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { canUseMembrane } from './deprecateObjectProperties'
2+
import warning from './routerWarning'
3+
4+
export default function makeStateWithLocation(state, location) {
5+
if (__DEV__ && canUseMembrane) {
6+
const stateWithLocation = { ...state }
7+
8+
// I don't use deprecateObjectProperties here because I want to keep the
9+
// same code path between development and production, in that we just
10+
// assign extra properties to the copy of the state object in both cases.
11+
for (const prop in location) {
12+
if (!Object.prototype.hasOwnProperty.call(location, prop)) {
13+
continue
14+
}
15+
16+
Object.defineProperty(stateWithLocation, prop, {
17+
get() {
18+
warning(false, 'Accessing location properties directly from the first argument to `getComponent`, `getComponents`, `getChildRoutes`, and `getIndexRoute` is deprecated. That argument is now the router state (`nextState` or `partialNextState`) rather than the location. To access the location, use `nextState.location` or `partialNextState.location`.')
19+
return location[prop]
20+
}
21+
})
22+
}
23+
24+
return stateWithLocation
25+
}
26+
27+
return { ...state, ...location }
28+
}

0 commit comments

Comments
 (0)