Skip to content
This repository was archived by the owner on Oct 26, 2018. It is now read-only.

Commit cb9d6b6

Browse files
committed
Redone docs.
1 parent a452791 commit cb9d6b6

File tree

4 files changed

+76
-80
lines changed

4 files changed

+76
-80
lines changed

README.md

Lines changed: 73 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,34 @@
22

33
[![npm version](https://img.shields.io/npm/v/react-router-redux.svg?style=flat-square)](https://www.npmjs.com/package/react-router-redux) [![npm downloads](https://img.shields.io/npm/dm/react-router-redux.svg?style=flat-square)](https://www.npmjs.com/package/react-router-redux) [![build status](https://img.shields.io/travis/rackt/react-router-redux/master.svg?style=flat-square)](https://travis-ci.org/rackt/react-router-redux)
44

5-
**Let react-router do all the work** :sparkles:
5+
> **Keep your router in sync with application state** :sparkles:
66
77
_Formerly known as redux-simple-router_
88

9-
[Redux](https://github.com/rackt/redux) is awesome. [React Router](https://github.com/rackt/react-router) is cool. The problem is that react-router manages an important piece of your application state: the URL. If you are using redux, you want your app state to fully represent your UI; if you snapshotted the app state, you should be able to load it up later and see the same thing.
9+
You're a smart person. You use [Redux](https://github.com/rackt/redux) to manage your application state. You use [React Router](https://github.com/rackt/react-router) to do routing. All is good.
1010

11-
react-router does a great job of mapping the current URL to a component tree, and continually does so with any URL changes. This is very useful, but we really want to store this state in redux as well.
11+
But the two libraries don't coordinate. You want to do time travel with your application state, but React Router doesn't navigate between pages when you replay actions. It controls an important part of application state: the URL.
1212

13-
The entire state that we are interested in boils down to one thing: the URL. This is an extremely simple library that just puts the URL in redux state and keeps it in sync with any react-router changes. Additionally, you can change the URL via redux and react-router will change accordingly.
13+
This library helps you keep that bit of state in sync with your Redux store. We keep a copy of the current location hidden in state. When you rewind your application state with a tool like [Redux DevTools](https://github.com/gaearon/redux-devtools), that state change is propagated to React Router so it can adjust the component tree accordingly. You can jump around in state, rewinding, replaying, and resetting as much as you'd like, and this library will ensure the two stay in sync at all times.
14+
15+
## Installation
1416

1517
```
16-
npm install react-router-redux
18+
npm install --save react-router-redux
1719
```
1820

1921
If you want to install the next major version, use `react-router-redux@next`. Run `npm dist-tag ls react-router-redux` to see what `next` is aliased to.
2022

21-
View the [CHANGELOG](https://github.com/rackt/react-router-redux/blob/master/CHANGELOG.md) for recent changes.
22-
23-
Read the [API docs](#api) farther down this page.
24-
25-
**Note:** We are [currently discussing some major changes](https://github.com/rackt/react-router-redux/issues/257) to the library. [React Router's API in 2.0](https://github.com/rackt/react-router/blob/master/upgrade-guides/v2.0.0.md) is significantly improved and makes things like action creators and reading location state from Redux obsolete. This library is still critical to enable things like time traveling and persisting state, so we're not going anywhere. But in many cases, you may not need this library and can simply use the provided React Router APIs. Go check them out and drop some technical debt. :smile:
26-
27-
### Usage
23+
## How It Works
2824

29-
The idea of this library is to use react-router's functionality exactly like its documentation tells you to. You can access all of its APIs in routing components. Additionally, you can use redux like you normally would, with a single app state.
25+
This library allows you to use React Router's APIs as they are documented. And, you can use redux like you normally would, with a single app state. The library simply enhances a history instance to allow it to synchronize any changes it receives into application state.
3026

31-
[redux](https://github.com/rackt/redux) (`store.routing`)  ↔  [**react-router-redux**](https://github.com/rackt/react-router-redux)  ↔  [history](https://github.com/rackt/history) (`history.location`)  ↔  [react-router](https://github.com/rackt/react-router)
27+
[history](https://github.com/rackt/history) + `store` ([redux](https://github.com/rackt/redux)) → [**react-router-redux**](https://github.com/rackt/react-router-redux) → enhanced [history](https://github.com/rackt/history) → [react-router](https://github.com/rackt/react-router)
3228

33-
We only store current URL and state, whereas redux-router stores the entire location object from react-router. You can read it, and also change it with an action.
34-
35-
### Tutorial
29+
## Tutorial
3630

3731
Let's take a look at a simple example.
3832

39-
**Note:** This example uses `react-router`'s 2.0 API, which is currently released under version 2.0.0-rc5.
40-
4133
```js
4234
import React from 'react'
4335
import ReactDOM from 'react-dom'
@@ -48,20 +40,20 @@ import { syncHistoryWithStore, routerReducer } from 'react-router-redux'
4840

4941
import reducers from '<project-path>/reducers'
5042

51-
const reducer = combineReducers(Object.assign({}, reducers, {
52-
routing: routerReducer
53-
}))
54-
55-
const store = createStore(reducer)
43+
// Add the reducer to your store on the `routing` key
44+
const store = createStore(
45+
combineReducers({
46+
...reducers,
47+
routing: routerReducer
48+
})
49+
)
5650

57-
// Sync dispatched route actions to the history
51+
// Create an enhanced history that syncs navigation events with the store
5852
const history = syncHistoryWithStore(browserHistory, store)
5953

60-
// Required for replaying actions from devtools to work
61-
reduxRouterMiddleware.listenForReplays(store)
62-
6354
ReactDOM.render(
6455
<Provider store={store}>
56+
/* Tell the Router to use our enhanced history */
6557
<Router history={history}>
6658
<Route path="/" component={App}>
6759
<Route path="foo" component={Foo}/>
@@ -73,31 +65,23 @@ ReactDOM.render(
7365
)
7466
```
7567

76-
Now you can read from `state.routing.locationBeforeTransitions.pathname` to get the URL. It's far more likely that you want to change the URL more often, however. You can use the `push` action creator that we provide:
68+
Now any time you navigate, which can come from pressing browser buttons or navigating in your application code, the enhanced history will first pass the new location through the Redux store and then on to React Router to update the component tree. If you time travel, it will also pass the new state to React Router to update the component tree again.
7769

78-
```js
79-
import { routeActions } from 'react-router-redux'
70+
#### How do I watch for navigation events, such as for analytics?
8071

81-
function MyComponent({ dispatch }) {
82-
return <Button onClick={() => dispatch(routeActions.push('/foo'))}/>;
83-
}
84-
```
85-
86-
This will change the state, which will trigger a change in react-router. Additionally, if you want to respond to the path update action, just handle the `CALL_HISTORY_METHOD` constant that we provide:
72+
Simply listen to the enhanced history via `history.listen`. This takes in a function that will receive a `location` any time the store updates. This includes any time travel activity performed on the store.
8773

8874
```js
89-
import { CALL_HISTORY_METHOD } from 'react-router-redux'
75+
const history = syncHistoryWithStore(browserHistory, store)
9076

91-
function update(state, action) {
92-
switch(action.type) {
93-
case CALL_HISTORY_METHOD:
94-
// do something here
95-
}
96-
}
77+
history.listen(location => analyticsService.track(location.pathname))
9778
```
98-
**But how do I access router props in a Container component?**
9979

100-
react-router [injects route information via a child component's props](https://github.com/rackt/react-router/blob/latest/docs/Introduction.md#getting-url-parameters). This makes accessing them from a simple component easy. When using a react-redux Container to connect simple components to the store state and dispatch you can access these injected route information from the [2nd argument of `mapStateToProps`](https://github.com/rackt/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) as follows:
80+
For other kinds of events in your system, you can use middleware on your Redux store like normal to watch any action that is dispatched to the store.
81+
82+
#### How do I access router state in a container component?
83+
84+
React Router [provides route information via a route component's props](https://github.com/rackt/react-router/blob/latest/docs/Introduction.md#getting-url-parameters). This makes it easy to access them from a container component. When using [react-redux](https://github.com/rackt/react-redux) to `connect()` your components to state, you can access the router's props from the [2nd argument of `mapStateToProps`](https://github.com/rackt/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options):
10185

10286
```js
10387
function mapStateToProps(state, ownProps) {
@@ -108,52 +92,64 @@ function mapStateToProps(state, ownProps) {
10892
}
10993
```
11094

95+
#### What if I want to issue navigation events via Redux actions?
11196

112-
### Examples
97+
React Router provides singleton versions of history (`browserHistory` and `hashHistory`) that you can import and use from anywhere in your application. However, if you prefer Redux style actions, the library also provides a set of action creators and a middleware to capture them and redirect them to your history instance.
11398

114-
* [examples/basic](https://github.com/rackt/react-router-redux/blob/master/examples/basic) - basic reference implementation
99+
```js
100+
import { routerMiddleware, push } from 'react-router-redux'
101+
102+
// Apply the middleware to the store
103+
const middleware = routerMiddleware(browserHistory)
104+
const store = createStore(
105+
reducers,
106+
applyMiddleware(middleware)
107+
)
108+
109+
// Dispatch from anywhere like normal.
110+
store.dispatch(push('/foo'))
111+
```
112+
113+
## Examples
114+
115+
- [examples/basic](/examples/basic) - basic reference implementation
115116

116117
Examples from the community:
117118

118-
* [davezuko/react-redux-starter-kit](https://github.com/davezuko/react-redux-starter-kit) - popular redux starter kit
119-
* **tip**: migrating from redux-router? use [this commit](https://github.com/davezuko/react-redux-starter-kit/commit/db66626ca8a02ecf030a3f7f5a669ac338fd5897) as a reference
120-
* [freeqaz/redux-simple-router-example](https://github.com/freeqaz/redux-simple-router-example) - example implementation
121-
* [choonkending/react-webpack-node](https://github.com/choonkending/react-webpack-node) - boilerplate for universal redux and react-router
122-
* [tj/frontend-boilerplate](https://github.com/tj/frontend-boilerplate)
123-
* [bdefore/universal-redux](https://github.com/bdefore/universal-redux) - npm package for universally rendered redux applications
124-
* [tomatau/breko-hub](https://github.com/tomatau/breko-hub) - Babel, React & Koa, Hot Universal Boilerplate - focused on developer experience.
125-
* [yangli1990/react-redux-isomorphic](https://github.com/yangli1990/Isomorphic-Universal-React-Template) - boilerplate for universal redux and redux-simple-router
126-
* [StevenIseki/redux-simple-router-example](https://github.com/StevenIseki/redux-simple-router-example)
127-
* [mattkrick/meatier](https://github.com/mattkrick/meatier) - SSR, dual dev/prod client builds
128-
* [mxstbr/react-boilerplate](https://github.com/mxstbr/react-boilerplate/tree/v3.0.0) - :fire: Quick setup for performance orientated, offline first React.js applications
129-
* **Tip**: Upgrading from react-router w/o react-router-redux? Use [this PR](https://github.com/mxstbr/react-boilerplate/pull/98/files) as a reference!
119+
- None yet, since we just released a new version :smile:
120+
121+
&rarr; _Have an example to add? Send us a PR!_ &larr;
122+
123+
## API
124+
125+
#### `routerReducer()`
130126

131-
_Have an example to add? Send us a PR!_
127+
**You must add this reducer to your store for syncing to work.**
132128

133-
### API
129+
A reducer function that stores location updates from `history`. If you use `combineReducers`, it should be nested under the `routing` key.
134130

135-
#### `history = syncHistoryWithStore(history: History, store)`
131+
#### `history = syncHistoryWithStore(history, store)`
136132

137-
We now sync by enhancing the history instance to listen for navigation events and dispatch those into the store. The enhanced history has its listen method overridden to respond to store changes, rather than directly to navigation events. When this history is provided to <Router>, the router will listen to it and receive these store changes. This means if we time travel with the store, the router will receive those store changes and update based on the location in the store, instead of what the browser says. Normal navigation events (hitting your browser back/forward buttons, telling a history singleton to push a location) flow through the history's listener like normal, so all the usual stuff works A-OK.
133+
Creates an enhanced history from the provided history. This history changes `history.listen` to pass all location updates through the provided store first. This ensures if the store is updated either from a navigation event or from a time travel action, such as a replay, the listeners of the enhanced history will stay in sync.
138134

139-
#### `routerReducer`
135+
**You must provide the enhanced history to your `<Router>` component.** This ensures your routes stay in sync with your location and your store at the same time.
140136

141-
A reducer function that keeps track of the router state. You must add this reducer to your app reducers when creating the store. It will return a `location` property in state. If you use `combineReducers`, it will be nested under wherever property you add it to (`state.routing` in the example above).
137+
#### `push(location)`, `replace(location)`, `go(number)`, `goBack()`, `goForward()`
142138

143-
**Warning:** It is a bad pattern to use `react-redux`'s `connect` decorator to map the state from this reducer to props on your `Route` components. This can lead to infinite loops and performance problems. `react-router` already provides this for you via `this.props.location`.
139+
**You must install `routerMiddleware` for these action creators to work.**
144140

145-
#### `CALL_HISTORY_METHOD`
141+
Action creators that correspond with the [history methods of the same name](https://github.com/rackt/history/blob/master/docs/GettingStarted.md#navigation). For reference they are defined as follows:
146142

147-
An action type that you can listen for in your reducers to be notified of route updates.
143+
- `push` - Pushes a new location to history, becoming the current location.
144+
- `replace` - Replaces the current location in history.
145+
- `go` - Moves backwards or forwards a relative number of locations in history.
146+
- `goForward` - Moves forward one location. Equivalent to `go(1)`
147+
- `goBack` - Moves backwards one location. Equivalent to `go(-1)`
148148

149-
#### `routeActions`
149+
Both `push` and `replace` take in a [location descriptor](https://github.com/rackt/history/blob/master/docs/Glossary.md#locationdescriptor), which can be an object describing the URL or a plain string URL.
150150

151-
An object that contains all the actions creators you can use to manipulate history:
151+
These action creators are also available in one single object as `routerActions`, which can be used as a convenience when using Redux's `bindActionCreators()`.
152152

153-
* `push(nextLocation: LocationDescriptor)`
154-
* `replace(nextLocation: LocationDescriptor)`
155-
* `go(n: number)`
156-
* `goForward()`
157-
* `goBack()`
153+
#### `routerMiddleware(history)`
158154

159-
A [location descriptor](https://github.com/rackt/history/blob/master/docs/Glossary.md#locationdescriptor) can be a descriptive object (see the link) or a normal URL string. The most common action is to push a new URL via `routeActions.push(...)`. These all directly call the analogous [history methods](https://github.com/rackt/history/blob/master/docs/GettingStarted.md#navigation).
155+
A middleware you can apply to your Redux `store` to capture dispatched actions created by the action creators. It will redirect those actions to the provided `history` instance.

src/actions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ export const go = updateLocation('go')
2323
export const goBack = updateLocation('goBack')
2424
export const goForward = updateLocation('goForward')
2525

26-
export const routeActions = { push, replace, go, goBack, goForward }
26+
export const routerActions = { push, replace, go, goBack, goForward }

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ export { LOCATION_CHANGE, routerReducer } from './reducer'
44
export {
55
CALL_HISTORY_METHOD,
66
push, replace, go, goBack, goForward,
7-
routeActions
7+
routerActions
88
} from './actions'
99
export routerMiddleware from './middleware'

test/actions.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
push, replace, go, goBack, goForward
66
} from '../src/actions'
77

8-
describe('routeActions', () => {
8+
describe('routerActions', () => {
99

1010
describe('push', () => {
1111
it('creates actions', () => {

0 commit comments

Comments
 (0)