Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
timdorr committed Apr 21, 2016
2 parents 1a73278 + 70c23b4 commit b3c37a8
Show file tree
Hide file tree
Showing 28 changed files with 264 additions and 127 deletions.
17 changes: 12 additions & 5 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
{
"stage": 0,
"loose": "all",
"plugins": [
"dev-expression"
]
"presets": ["stage-0", "react"],
"plugins": ["dev-expression"],

"env": {
"cjs": {
"presets": ["es2015-loose"],
"plugins": ["add-module-exports"]
},
"es": {
"presets": ["es2015-loose-native-modules"]
}
}
}
13 changes: 9 additions & 4 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
## [HEAD]
> Unreleased
## [v2.3.0]
> April 18, 2016
- **Feature:** Added `applyRouterMiddleware` ([#3327])
- **Feature:** Add `applyRouterMiddleware` for extending router rendering ([#3327])
- **Feature/Deprecation:** Add `routerShape` and `locationShape` as top-level exported prop types, and deprecate all the old prop types, including the ones that were previously incorrectly removed ([#3349])
- **Minor:** Move ES module build back to `es6/` to avoid breaking people who were incorrectly importing from `react-router/es6` ([#3334])

[HEAD]: https://github.com/reactjs/react-router/compare/v2.2.4...master
[v2.3.0]: https://github.com/reactjs/react-router/compare/v2.2.4...v2.3.0
[#3327]: https://github.com/reactjs/react-router/issues/3327
[#3334]: https://github.com/reactjs/react-router/issues/3334
[#3349]: https://github.com/reactjs/react-router/issues/3349


## [v2.2.4]
> April 15, 2016
Expand Down
70 changes: 61 additions & 9 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,67 @@ An `<IndexLink>` is like a [`<Link>`](#link), except it is only active when the
### `<RouterContext>`
A `<RouterContext>` renders the component tree for a given router state. Its used by `<Router>` but also useful for server rendering and integrating in brownfield development.

It also provides a `router` object on `context`.
It also provides a `router` object on [context](https://facebook.github.io/react/docs/context.html).

#### `context.router`

Contains data and methods relevant to routing. Most useful for imperatively transitioning around the application.

To use it, you must signal to React that you need it by declaring your use of it in your component via `contextTypes`:

```js
var MyComponent = React.createClass({
contextTypes: {
router: routerShape.isRequired
},

render: function() {
// Here, you can use this.context.router.
}
})
```

To use `context.router` on a component declared as an ES2015 class, define `contextTypes` as a static property of the class:

```js
class MyComponent extends React.Component {
render() {
// Here, you can use this.context.router.
}
}

MyComponent.contextTypes = {
router: routerShape.isRequired
}
```

If you are using the class properties proposal, you can instead write:

```js
class MyComponent extends React.Component {
static contextTypes = {
router: routerShape.isRequired
}

render() {
// Here, you can use this.context.router.
}
}
```

To use `context.router` with
[stateless function components](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions), declare `contextTypes` as a static property of the component function:

```js
function MyComponent(props, context) {
// Here, you can use context.router.
}

MyComponent.contextTypes = {
router: routerShape.isRequired
}
```

##### `push(pathOrLoc)`
Transitions to a new URL, adding a new entry in the browser history.

Expand Down Expand Up @@ -639,14 +694,11 @@ One or many [`<Route>`](#route)s or [`PlainRoute`](#plainroute)s.


### `PropTypes`
The following objects are exposed as properties of the exported PropTypes object:
- `falsy`: Checks that a component does not have a prop
- `history`
- `location`
- `component`
- `components`
- `route`
- `routes`
The following prop types are exported at top level and from `react-router/lib/PropTypes`:
- `routerShape`: Shape for the `router` object on context
- `locationShape`: Shape for the `location` object on route component props

Previously, a number of prop types intended for internal use were also exported under `PropTypes`. These are deprecated and should not be used.


### `useRoutes(createHistory)` (deprecated)
Expand Down
1 change: 1 addition & 0 deletions docs/Glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ A *route pattern* (or "path") is a string that describes a portion of a URL. Pat
- `:paramName` – matches a URL segment up to the next `/`, `?`, or `#`. The matched string is called a [param](#params)
- `()` – Wraps a portion of the URL that is optional
- `*` – Matches all characters (non-greedy) up to the next character in the pattern, or to the end of the URL if there is none, and creates a `splat` [param](#params)
- `**` - Matches all characters (greedy) until the next `/`, `?`, or `#` and creates a `splat` [param](#params)
Route patterns are relative to the pattern of the parent route unless they begin with a `/`, in which case they begin matching at the beginning of the URL.
Expand Down
2 changes: 1 addition & 1 deletion docs/Troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ You need to add `router` to your component's `contextTypes` to make the router o

```js
contextTypes: {
router: Router.PropTypes.router
router: routerShape.isRequired
}
```

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/ConfirmingNavigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ You can prevent a transition from happening or prompt the user before leaving a
const Home = React.createClass({

contextTypes: {
router: Router.PropTypes.router
router: routerShape.isRequired
},

componentDidMount() {
Expand Down
8 changes: 5 additions & 3 deletions examples/auth-flow-async-with-query-params/app.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { createClass, PropTypes } from 'react'
import React, { createClass } from 'react'
import { render } from 'react-dom'
import { Router, Route, IndexRoute, browserHistory, Link } from 'react-router'
import {
Router, Route, IndexRoute, browserHistory, Link, routerShape
} from 'react-router'

function App(props) {
return (
Expand All @@ -12,7 +14,7 @@ function App(props) {

const Form = createClass({
contextTypes: {
router: PropTypes.object.isRequired
router: routerShape.isRequired
},

getInitialState() {
Expand Down
4 changes: 2 additions & 2 deletions examples/auth-flow/app.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { render } from 'react-dom'
import { browserHistory, Router, Route, Link } from 'react-router'
import { browserHistory, Router, Route, Link, routerShape } from 'react-router'
import auth from './auth'

const App = React.createClass({
Expand Down Expand Up @@ -58,7 +58,7 @@ const Dashboard = React.createClass({
const Login = React.createClass({

contextTypes: {
router: React.PropTypes.object.isRequired
router: routerShape.isRequired
},

getInitialState() {
Expand Down
4 changes: 2 additions & 2 deletions examples/confirming-navigation/app.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { render } from 'react-dom'
import { browserHistory, Router, Route, Link } from 'react-router'
import { browserHistory, Router, Route, Link, routerShape } from 'react-router'

const App = React.createClass({
render() {
Expand All @@ -24,7 +24,7 @@ const Dashboard = React.createClass({

const Form = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: routerShape.isRequired
},

componentWillMount() {
Expand Down
8 changes: 5 additions & 3 deletions examples/master-detail/app.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import { render, findDOMNode } from 'react-dom'
import { browserHistory, Router, Route, IndexRoute, Link } from 'react-router'
import {
browserHistory, Router, Route, IndexRoute, Link, routerShape
} from 'react-router'
import ContactStore from './ContactStore'
import './app.css'

Expand Down Expand Up @@ -63,7 +65,7 @@ const Index = React.createClass({

const Contact = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: routerShape.isRequired
},

getStateFromStore(props) {
Expand Down Expand Up @@ -120,7 +122,7 @@ const Contact = React.createClass({

const NewContact = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: routerShape.isRequired
},

createContact(event) {
Expand Down
4 changes: 2 additions & 2 deletions examples/passing-props-to-children/app.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react'
import { render } from 'react-dom'
import { browserHistory, Router, Route, Link } from 'react-router'
import { browserHistory, Router, Route, Link, routerShape } from 'react-router'
import './app.css'

const App = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: routerShape.isRequired
},

getInitialState() {
Expand Down
2 changes: 1 addition & 1 deletion modules/History.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import warning from './routerWarning'
import { history } from './PropTypes'
import { history } from './InternalPropTypes'

/**
* A mixin that adds the "history" instance variable to components.
Expand Down
2 changes: 1 addition & 1 deletion modules/IndexRedirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import warning from './routerWarning'
import invariant from 'invariant'
import Redirect from './Redirect'
import { falsy } from './PropTypes'
import { falsy } from './InternalPropTypes'

const { string, object } = React.PropTypes

Expand Down
2 changes: 1 addition & 1 deletion modules/IndexRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import warning from './routerWarning'
import invariant from 'invariant'
import { createRouteFromReactElement } from './RouteUtils'
import { component, components, falsy } from './PropTypes'
import { component, components, falsy } from './InternalPropTypes'

const { func } = React.PropTypes

Expand Down
22 changes: 22 additions & 0 deletions modules/InternalPropTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { PropTypes } from 'react'

const { func, object, arrayOf, oneOfType, element, shape, string } = PropTypes

export function falsy(props, propName, componentName) {
if (props[propName])
return new Error(`<${componentName}> should not have a "${propName}" prop`)
}

export const history = shape({
listen: func.isRequired,
push: func.isRequired,
replace: func.isRequired,
go: func.isRequired,
goBack: func.isRequired,
goForward: func.isRequired
})

export const component = oneOfType([ func, string ])
export const components = oneOfType([ component, object ])
export const route = oneOfType([ object, element ])
export const routes = oneOfType([ route, arrayOf(route) ])
3 changes: 2 additions & 1 deletion modules/Link.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import warning from './routerWarning'
import { routerShape } from './PropTypes'

const { bool, object, string, func, oneOfType } = React.PropTypes

Expand Down Expand Up @@ -49,7 +50,7 @@ function createLocationDescriptor(to, { query, hash, state }) {
const Link = React.createClass({

contextTypes: {
router: object
router: routerShape
},

propTypes: {
Expand Down
57 changes: 26 additions & 31 deletions modules/PatternUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,37 +94,29 @@ export function matchPattern(pattern, pathname) {
}

const match = pathname.match(new RegExp(`^${regexpSource}`, 'i'))
if (match == null) {
return null
}

const matchedPath = match[0]
let remainingPathname = pathname.substr(matchedPath.length)

let remainingPathname, paramValues
if (match != null) {
const matchedPath = match[0]
remainingPathname = pathname.substr(matchedPath.length)

if (remainingPathname) {
// Require that the match ends at a path separator, if we didn't match
// the full path, so any remaining pathname is a new path segment.
if (matchedPath.charAt(matchedPath.length - 1) !== '/') {
return {
remainingPathname: null,
paramNames,
paramValues: null
}
}

// If there is a remaining pathname, treat the path separator as part of
// the remaining pathname for properly continuing the match.
remainingPathname = `/${remainingPathname}`
if (remainingPathname) {
// Require that the match ends at a path separator, if we didn't match
// the full path, so any remaining pathname is a new path segment.
if (matchedPath.charAt(matchedPath.length - 1) !== '/') {
return null
}

paramValues = match.slice(1).map(v => v && decodeURIComponent(v))
} else {
remainingPathname = paramValues = null
// If there is a remaining pathname, treat the path separator as part of
// the remaining pathname for properly continuing the match.
remainingPathname = `/${remainingPathname}`
}

return {
remainingPathname,
paramNames,
paramValues
paramValues: match.slice(1).map(v => v && decodeURIComponent(v))
}
}

Expand All @@ -133,16 +125,19 @@ export function getParamNames(pattern) {
}

export function getParams(pattern, pathname) {
const { paramNames, paramValues } = matchPattern(pattern, pathname)

if (paramValues != null) {
return paramNames.reduce(function (memo, paramName, index) {
memo[paramName] = paramValues[index]
return memo
}, {})
const match = matchPattern(pattern, pathname)
if (!match) {
return null
}

return null
const { paramNames, paramValues } = match
const params = {}

paramNames.forEach((paramName, index) => {
params[paramName] = paramValues[index]
})

return params
}

/**
Expand Down
Loading

0 comments on commit b3c37a8

Please sign in to comment.