Skip to content

Commit

Permalink
Update docs, examples, and upgrade guide.
Browse files Browse the repository at this point in the history
Also add an export of withRouter
  • Loading branch information
timdorr committed Apr 20, 2016
1 parent 16ea437 commit e89a5cb
Show file tree
Hide file tree
Showing 13 changed files with 321 additions and 329 deletions.
59 changes: 4 additions & 55 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- [`<Router>`](#router)
- [`<Link>`](#link)
- [`<IndexLink>`](#indexlink)
- [`withRouter`](#withRouter-component)
- [`<RouterContext>`](#routercontext)
- [`context.router`](#contextrouter)
- `<RoutingContext>` (deprecated, use `<RouterContext>`)
Expand Down Expand Up @@ -162,6 +163,9 @@ Given a route like `<Route path="/users/:userId" />`:
### `<IndexLink>`
An `<IndexLink>` is like a [`<Link>`](#link), except it is only active when the current route is exactly the linked route. It is equivalent to `<Link>` with the `onlyActiveOnIndex` prop set.

### `withRouter(component)`
A HoC (higher-order component) that wraps another component to provide `this.props.router`. Pass in your component and it will return the wrapped component.

### `<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.

Expand All @@ -171,61 +175,6 @@ It also provides a `router` object on [context](https://facebook.github.io/react

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
12 changes: 7 additions & 5 deletions docs/Troubleshooting.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Troubleshooting

### `this.context.router` is `undefined`
### `this.props.router` is `undefined`

You need to add `router` to your component's `contextTypes` to make the router object available to you.
You need to wrap your component using `withRouter` to make the router object available to you.

```js
contextTypes: {
router: routerShape.isRequired
}
const Component = withRouter(
React.createClass({
//...
})
)
```


Expand Down
32 changes: 17 additions & 15 deletions docs/guides/ConfirmingNavigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,26 @@
You can prevent a transition from happening or prompt the user before leaving a [route](/docs/Glossary.md#route) with a leave hook.

```js
const Home = React.createClass({
const Home = withRouter(
React.createClass({

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

componentDidMount() {
this.context.router.setRouteLeaveHook(this.props.route, this.routerWillLeave)
},
componentDidMount() {
this.props.router.setRouteLeaveHook(this.props.route, this.routerWillLeave)
},

routerWillLeave(nextLocation) {
// return false to prevent a transition w/o prompting the user,
// or return a string to allow the user to decide:
if (!this.state.isSaved)
return 'Your work is not saved! Are you sure you want to leave?'
},
routerWillLeave(nextLocation) {
// return false to prevent a transition w/o prompting the user,
// or return a string to allow the user to decide:
if (!this.state.isSaved)
return 'Your work is not saved! Are you sure you want to leave?'
},

// ...
// ...

})
})
)
```
2 changes: 1 addition & 1 deletion docs/guides/NavigatingOutsideOfComponents.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Navigating Outside of Components

While you can use `this.context.router` to navigate around, many apps want to be able to navigate outside of their components. They can do that with the history the app gives to `Router`.
While you can use `this.props.router` from `withRouter` to navigate around, many apps want to be able to navigate outside of their components. They can do that with the history the app gives to `Router`.

```js
// your main file that renders a Router
Expand Down
67 changes: 34 additions & 33 deletions examples/auth-flow-async-with-query-params/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { createClass } from 'react'
import { render } from 'react-dom'
import {
Router, Route, IndexRoute, browserHistory, Link, routerShape
Router, Route, IndexRoute, browserHistory, Link, withRouter
} from 'react-router'

function App(props) {
Expand All @@ -12,43 +12,44 @@ function App(props) {
)
}

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

getInitialState() {
return {
value: ''
}
},
displayName: 'Form',

submitAction(event) {
event.preventDefault()
this.context.router.push({
pathname: '/page',
query: {
qsparam: this.state.value
getInitialState() {
return {
value: ''
}
})
},
},

handleChange(event) {
this.setState({ value: event.target.value })
},
submitAction(event) {
event.preventDefault()
this.props.router.push({
pathname: '/page',
query: {
qsparam: this.state.value
}
})
},

render() {
return (
<form onSubmit={this.submitAction}>
<p>Token is <em>pancakes</em></p>
<input type="text" value={this.state.value} onChange={this.handleChange} />
<button type="submit">Submit the thing</button>
<p><Link to="/page?qsparam=pancakes">Or authenticate via URL</Link></p>
<p><Link to="/page?qsparam=bacon">Or try failing to authenticate via URL</Link></p>
</form>
)
}
})
handleChange(event) {
this.setState({ value: event.target.value })
},

render() {
return (
<form onSubmit={this.submitAction}>
<p>Token is <em>pancakes</em></p>
<input type="text" value={this.state.value} onChange={this.handleChange} />
<button type="submit">Submit the thing</button>
<p><Link to="/page?qsparam=pancakes">Or authenticate via URL</Link></p>
<p><Link to="/page?qsparam=bacon">Or try failing to authenticate via URL</Link></p>
</form>
)
}
})
)

function Page() {
return <h1>Hey, I see you are authenticated. Welcome!</h1>
Expand Down
86 changes: 43 additions & 43 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, routerShape } from 'react-router'
import { browserHistory, Router, Route, Link, withRouter } from 'react-router'
import auth from './auth'

const App = React.createClass({
Expand Down Expand Up @@ -55,51 +55,51 @@ const Dashboard = React.createClass({
}
})

const Login = React.createClass({
const Login = withRouter(
React.createClass({

contextTypes: {
router: routerShape.isRequired
},

getInitialState() {
return {
error: false
}
},

handleSubmit(event) {
event.preventDefault()

const email = this.refs.email.value
const pass = this.refs.pass.value

auth.login(email, pass, (loggedIn) => {
if (!loggedIn)
return this.setState({ error: true })

const { location } = this.props
displayName: 'Login',

if (location.state && location.state.nextPathname) {
this.context.router.replace(location.state.nextPathname)
} else {
this.context.router.replace('/')
getInitialState() {
return {
error: false
}
})
},

render() {
return (
<form onSubmit={this.handleSubmit}>
<label><input ref="email" placeholder="email" defaultValue="[email protected]" /></label>
<label><input ref="pass" placeholder="password" /></label> (hint: password1)<br />
<button type="submit">login</button>
{this.state.error && (
<p>Bad login information</p>
)}
</form>
)
}
})
},

handleSubmit(event) {
event.preventDefault()

const email = this.refs.email.value
const pass = this.refs.pass.value

auth.login(email, pass, (loggedIn) => {
if (!loggedIn)
return this.setState({ error: true })

const { location } = this.props

if (location.state && location.state.nextPathname) {
this.props.router.replace(location.state.nextPathname)
} else {
this.props.router.replace('/')
}
})
},

render() {
return (
<form onSubmit={this.handleSubmit}>
<label><input ref="email" placeholder="email" defaultValue="[email protected]" /></label>
<label><input ref="pass" placeholder="password" /></label> (hint: password1)<br />
<button type="submit">login</button>
{this.state.error && (
<p>Bad login information</p>
)}
</form>
)
}
})
)

const About = React.createClass({
render() {
Expand Down
12 changes: 5 additions & 7 deletions examples/auth-with-shared-root/components/Login.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import React from 'react'
import { withRouter } from 'react-router'
import auth from '../utils/auth.js'

const Login = React.createClass({

contextTypes: {
router: React.PropTypes.object
},
displayName: 'Login',

getInitialState() {
return {
Expand All @@ -26,9 +24,9 @@ const Login = React.createClass({
const { location } = this.props

if (location.state && location.state.nextPathname) {
this.context.router.replace(location.state.nextPathname)
this.props.router.replace(location.state.nextPathname)
} else {
this.context.router.replace('/')
this.props.router.replace('/')
}
})
},
Expand All @@ -48,4 +46,4 @@ const Login = React.createClass({

})

export default Login
export default withRouter(Login)
Loading

0 comments on commit e89a5cb

Please sign in to comment.