Skip to content

Commit 3cc2e30

Browse files
committed
Merge remote-tracking branch 'ff/master'
2 parents cd8f1ba + 0f5b493 commit 3cc2e30

File tree

13 files changed

+101
-68
lines changed

13 files changed

+101
-68
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ thought, not an after-thought.
1818
- [Changelog](/CHANGELOG.md)
1919
- [#react-router channel on reactiflux](http://www.reactiflux.com/)
2020

21+
**Note:** *If you are still using React Router 0.13.x [the docs](https://github.com/rackt/react-router/tree/0.13.x/docs/guides) can be found on [the 0.13.x branch](https://github.com/rackt/react-router/tree/0.13.x).*
22+
2123
### Browser Support
2224

2325
We support all browsers and environments where React runs.

UPGRADE_GUIDE.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ let history = createBrowserHistory()
5555
React.render(<Router history={history}>{routes}</Router>, el)
5656
```
5757

58+
After updating to 1.0.0 you will notice that a magic querystring entry starts appearing in your URLs called "_k". An example of how it looks is this: `?_k=umhx1s`.
59+
60+
This is not a bug - this is intended. You can read more about the feature [here](https://github.com/rackt/react-router/blob/master/docs/guides/basics/Histories.md#what-is-that-_kckuvup-junk-in-the-url) and how to opt out [here](https://rackt.github.io/history/stable/HashHistoryCaveats.html).
61+
5862
### Route Config
5963

6064
You can still nest your routes as before, paths are inherited from
@@ -116,11 +120,11 @@ since it's simple with a `*` path.
116120
#### "active" class
117121

118122
In 0.13.x links added the "active" class by default which you could
119-
override with `activeClassName`, or provide `activeStyles`. Most links
123+
override with `activeClassName`, or provide `activeStyle`s. Most links
120124
don't need this and the check is (currently) expensive.
121125

122126
Links no longer add the "active" class by default, you opt-in by
123-
providing one; if no `activeClassName` or `activeStyles` are provided,
127+
providing one; if no `activeClassName` or `activeStyle`s are provided,
124128
the link will not check if it's active.
125129

126130
```js

docs/Introduction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ const App = React.createClass({
113113
return (
114114
<div>
115115
<h1>App</h1>
116-
{/* change the <a>s to <Links>s */}
116+
{/* change the <a>s to <Link>s */}
117117
<ul>
118118
<li><Link to="/about">About</Link></li>
119119
<li><Link to="/inbox">Inbox</Link></li>

docs/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22

33
* [Introduction](/docs/Introduction.md)
44
* [Basics](/docs/guides/basics/README.md)
5+
* [Route Configuration](/docs/guides/basics/RouteConfiguration.md)
6+
* [Route Matching](/docs/guides/basics/RouteMatching.md)
7+
* [Histories](/docs/guides/basics/Histories.md)
8+
* [Index Routes and Links](/docs/guides/basics/IndexRoutes.md)
59
* [Advanced Usage](/docs/guides/advanced/README.md)
10+
* [Dynamic Routing](/docs/guides/advanced/DynamicRouting.md)
11+
* [Confirming Navigation](/docs/guides/advanced/ConfirmingNavigation.md)
12+
* [Server Rendering](/docs/guides/advanced/ServerRendering.md)
13+
* [Component Lifecycle](/docs/guides/advanced/ComponentLifecycle.md)
14+
* [Navigating Outside of Components](/docs/guides/advanced/NavigatingOutsideOfComponents.md)
615
* [Upgrade Guide](/UPGRADE_GUIDE.md)
716
* [Troubleshooting](/docs/Troubleshooting.md)
817
* [API](/docs/API.md)
Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,38 @@
11
# Server Rendering
22

3-
Server rendering is a bit different than in a client because you'll want
4-
to:
3+
Server rendering is a bit different than in a client because you'll want to:
54

65
- Send `500` responses for errors
76
- Send `30x` responses for redirects
87
- Fetch data before rendering (and use the router to help you do it)
98

10-
To facilitate these needs, you drop one level lower than the [`<Router/>`](/docs/API.md#Router)
11-
API with:
9+
To facilitate these needs, you drop one level lower than the [`<Router>`](/docs/API.md#Router) API with:
1210

13-
- `createLocation` from the history package
1411
- `match` to match the routes to a location without rendering
1512
- `RoutingContext` for synchronous rendering of route components
1613

1714
It looks something like this with an imaginary JavaScript server:
1815

1916
```js
20-
import createLocation from 'history/lib/createLocation'
21-
import { RoutingContext, match } from 'react-router'
22-
import routes from './routes'
2317
import { renderToString } from 'react-dom/server'
18+
import { match, RoutingContext } from 'react-router'
19+
import routes from './routes'
2420

2521
serve((req, res) => {
26-
let location = createLocation(req.url)
27-
28-
match({ routes, location }, (error, redirectLocation, renderProps) => {
29-
if (redirectLocation)
30-
res.redirect(301, redirectLocation.pathname + redirectLocation.search)
31-
else if (error)
22+
// Note that req.url here should be the full URL path from
23+
// the original request, including the query string.
24+
match(req.url, (error, redirectLocation, renderProps) => {
25+
if (redirectLocation) {
26+
res.redirect(302, redirectLocation.pathname + redirectLocation.search)
27+
} else if (error) {
3228
res.send(500, error.message)
33-
else if (renderProps == null)
29+
} else if (renderProps == null) {
3430
res.send(404, 'Not found')
35-
else
36-
res.send(renderToString(<RoutingContext {...renderProps}/>))
31+
} else {
32+
res.send(200, renderToString(<RoutingContext {...renderProps} />))
33+
}
3734
})
3835
})
3936
```
4037

41-
For data loading, you can use the `renderProps` argument to build whatever
42-
convention you want--like adding static `load` methods to your route
43-
components, or putting data loading functions on the routes, it's up to
44-
you.
38+
For data loading, you can use the `renderProps` argument to build whatever convention you want--like adding static `load` methods to your route components, or putting data loading functions on the routes--it's up to you.

docs/guides/basics/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
* [Route Configuration](RouteConfiguration.md)
44
* [Route Matching](RouteMatching.md)
55
* [Histories](Histories.md)
6+
* [Index Routes and Links](IndexRoutes.md)

modules/__tests__/matchRoutes-test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import Route from '../Route'
44

55
import assert from 'assert'
66
import expect from 'expect'
7-
import { createLocation } from 'history'
7+
import { createMemoryHistory } from 'history'
88
import { createRoutes } from '../RouteUtils'
99
import matchRoutes from '../matchRoutes'
1010

1111
describe('matchRoutes', function () {
1212

1313
let routes, RootRoute, UsersRoute, UsersIndexRoute, UserRoute, PostRoute, FilesRoute, AboutRoute, TeamRoute, ProfileRoute, CatchAllRoute
14+
let createLocation = createMemoryHistory().createLocation
1415
beforeEach(function () {
1516
/*
1617
<Route>

modules/__tests__/serverRendering-test.js

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
/*eslint react/prop-types: 0*/
33
import expect from 'expect'
44
import React from 'react'
5-
import createLocation from 'history/lib/createLocation'
6-
import RoutingContext from '../RoutingContext'
75
import match from '../match'
6+
import RoutingContext from '../RoutingContext'
87
import Link from '../Link'
98

109
describe('server rendering', function () {
@@ -71,8 +70,7 @@ describe('server rendering', function () {
7170
})
7271

7372
it('works', function (done) {
74-
const location = createLocation('/dashboard')
75-
match({ routes, location }, function (error, redirectLocation, renderProps) {
73+
match({ routes, location: '/dashboard' }, function (error, redirectLocation, renderProps) {
7674
const string = React.renderToString(
7775
<RoutingContext {...renderProps} />
7876
)
@@ -82,8 +80,7 @@ describe('server rendering', function () {
8280
})
8381

8482
it('renders active Links as active', function (done) {
85-
const location = createLocation('/about')
86-
match({ routes, location }, function (error, redirectLocation, renderProps) {
83+
match({ routes, location: '/about' }, function (error, redirectLocation, renderProps) {
8784
const string = React.renderToString(
8885
<RoutingContext {...renderProps} />
8986
)
@@ -94,8 +91,7 @@ describe('server rendering', function () {
9491
})
9592

9693
it('sends the redirect location', function (done) {
97-
const location = createLocation('/company')
98-
match({ routes, location }, function (error, redirectLocation) {
94+
match({ routes, location: '/company' }, function (error, redirectLocation) {
9995
expect(redirectLocation).toExist()
10096
expect(redirectLocation.pathname).toEqual('/about')
10197
expect(redirectLocation.search).toEqual('')
@@ -106,11 +102,10 @@ describe('server rendering', function () {
106102
})
107103

108104
it('sends null values when no routes match', function (done) {
109-
const location = createLocation('/no-match')
110-
match({ routes, location }, function (error, redirectLocation, state) {
111-
expect(error).toBe(null)
112-
expect(redirectLocation).toBe(null)
113-
expect(state).toBe(null)
105+
match({ routes, location: '/no-match' }, function (error, redirectLocation, state) {
106+
expect(error).toNotExist()
107+
expect(redirectLocation).toNotExist()
108+
expect(state).toNotExist()
114109
done()
115110
})
116111
})

modules/__tests__/transitionHooks-test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import expect, { spyOn } from 'expect'
44
import React from 'react'
55
import createHistory from 'history/lib/createMemoryHistory'
6+
import useQueries from 'history/lib/useQueries'
67
import execSteps from './execSteps'
78
import Router from '../Router'
89

@@ -193,4 +194,19 @@ describe('When a router enters a branch', function () {
193194
})
194195
})
195196

197+
describe('and then the query changes', function () {
198+
it('calls the onEnter hooks of all routes in that branch', function (done) {
199+
const newsFeedRouteEnterSpy = spyOn(NewsFeedRoute, 'onEnter').andCallThrough()
200+
const history = useQueries(createHistory)('/inbox')
201+
202+
React.render(<Router history={history} routes={routes}/>, node, function () {
203+
history.pushState(null, '/news', { q: 1 })
204+
expect(newsFeedRouteEnterSpy.calls.length).toEqual(1)
205+
history.pushState(null, '/news', { q: 2 })
206+
expect(newsFeedRouteEnterSpy.calls.length).toEqual(2)
207+
done()
208+
})
209+
})
210+
})
211+
196212
})

modules/computeChangedRoutes.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ function routeParamsChanged(route, prevState, nextState) {
1111
})
1212
}
1313

14+
function routeQueryChanged(prevState, nextState) {
15+
return prevState.location.search !== nextState.location.search
16+
}
17+
1418
/**
1519
* Returns an object of { leaveRoutes, enterRoutes } determined by
1620
* the change from prevState to nextState. We leave routes if either
1721
* 1) they are not in the next state or 2) they are in the next state
18-
* but their params have changed (i.e. /users/123 => /users/456).
22+
* but their params have changed (i.e. /users/123 => /users/456) or
23+
* 3) they are in the next state but the query has changed
24+
* (i.e. /search?query=foo => /search?query=bar)
1925
*
2026
* leaveRoutes are ordered starting at the leaf route of the tree
2127
* we're leaving up to the common parent route. enterRoutes are ordered
@@ -28,7 +34,9 @@ function computeChangedRoutes(prevState, nextState) {
2834
let leaveRoutes, enterRoutes
2935
if (prevRoutes) {
3036
leaveRoutes = prevRoutes.filter(function (route) {
31-
return nextRoutes.indexOf(route) === -1 || routeParamsChanged(route, prevState, nextState)
37+
return nextRoutes.indexOf(route) === -1
38+
|| routeParamsChanged(route, prevState, nextState)
39+
|| routeQueryChanged(prevState, nextState)
3240
})
3341

3442
// onLeave hooks start at the leaf route.

0 commit comments

Comments
 (0)