You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Oct 26, 2018. It is now read-only.
> **Keep your router in sync with application state**:sparkles:
6
6
7
7
_Formerly known as redux-simple-router_
8
8
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.
10
10
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.
12
12
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
14
16
15
17
```
16
-
npm install react-router-redux
18
+
npm install --save react-router-redux
17
19
```
18
20
19
21
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.
20
22
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
28
24
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.
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
36
30
37
31
Let's take a look at a simple example.
38
32
39
-
**Note:** This example uses `react-router`'s 2.0 API, which is currently released under version 2.0.0-rc5.
// Required for replaying actions from devtools to work
61
-
reduxRouterMiddleware.listenForReplays(store)
62
-
63
54
ReactDOM.render(
64
55
<Provider store={store}>
56
+
/* Tell the Router to use our enhanced history */
65
57
<Router history={history}>
66
58
<Route path="/" component={App}>
67
59
<Route path="foo" component={Foo}/>
@@ -73,31 +65,23 @@ ReactDOM.render(
73
65
)
74
66
```
75
67
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.
77
69
78
-
```js
79
-
import { routeActions } from'react-router-redux'
70
+
#### How do I watch for navigation events, such as for analytics?
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.
**But how do I access router props in a Container component?**
99
79
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):
101
85
102
86
```js
103
87
functionmapStateToProps(state, ownProps) {
@@ -108,52 +92,64 @@ function mapStateToProps(state, ownProps) {
108
92
}
109
93
```
110
94
95
+
#### What if I want to issue navigation events via Redux actions?
111
96
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.
*[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
*[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
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.
138
134
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.
140
136
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).
**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.**
144
140
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:
146
142
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)`
148
148
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.
150
150
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()`.
152
152
153
-
*`push(nextLocation: LocationDescriptor)`
154
-
*`replace(nextLocation: LocationDescriptor)`
155
-
*`go(n: number)`
156
-
*`goForward()`
157
-
*`goBack()`
153
+
#### `routerMiddleware(history)`
158
154
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.
0 commit comments