UNPKG

8.85 kBMarkdownView Raw
1# redux-simple-router
2
3[![npm version](https://img.shields.io/npm/v/redux-simple-router.svg?style=flat-square)](https://www.npmjs.com/package/redux-simple-router) [![npm downloads](https://img.shields.io/npm/dm/redux-simple-router.svg?style=flat-square)](https://www.npmjs.com/package/redux-simple-router) [![build status](https://img.shields.io/travis/rackt/redux-simple-router/master.svg?style=flat-square)](https://travis-ci.org/rackt/redux-simple-router)
4
5**Let react-router do all the work** :sparkles:
6
7[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.
8
9react-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.
10
11The 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.
12
13```
14npm install redux-simple-router
15```
16
17If you want to install the next major version, use `redux-simple-router@next`. Run `npm dist-tag ls redux-simple-router` to see what `next` is aliased to.
18
19View the [CHANGELOG](https://github.com/jlongster/redux-simple-router/blob/master/CHANGELOG.md) for recent changes.
20
21Read the [API docs](#api) farther down this page.
22
23##### _What about redux-router?_
24
25[redux-router](https://github.com/rackt/redux-router) is another project which solves the same problem. However, it's far more complex. Take a quick look at [the code for this library](https://github.com/jlongster/redux-simple-router/blob/master/src/index.js)—it's extremely minimal. redux-router is much bigger and more complex.
26
27That said, redux-router is a fine project and has features this doesn't provide. Use it if you like it better.
28
29**Compared with redux-router:**
30
31* Much smaller and simpler. You don't need to learn another library on top of everything else.
32* We encourage direct access of react-router APIs. Need server-side rendering, or something else advanced? Just read react-router's docs.
33* We only store current URL and state, whereas redux-router stores the entire location object from react-router.
34
35### Usage
36
37The 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 and "connected" components. It's even possible for a single component to be both if needed.
38
39[redux](https://github.com/rackt/redux) (`store.routing`)  ↔  [**redux-simple-router**](https://github.com/jlongster/redux-simple-router)  ↔  [history](https://github.com/rackt/history) (`history.location`)  ↔  [react-router](https://github.com/rackt/react-router)
40
41We 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.
42
43### Tutorial
44
45Let's take a look at a simple example.
46
47```js
48import React from 'react'
49import ReactDOM from 'react-dom'
50import { compose, createStore, combineReducers, applyMiddleware } from 'redux'
51import { Provider } from 'react-redux'
52import { Router, Route } from 'react-router'
53import { createHistory } from 'history'
54import { syncHistory, routeReducer } from 'redux-simple-router'
55import reducers from '<project-path>/reducers'
56
57const reducer = combineReducers(Object.assign({}, reducers, {
58 routing: routeReducer
59}))
60const history = createHistory()
61
62// Sync dispatched route actions to the history
63const reduxRouterMiddleware = syncHistory(history)
64const createStoreWithMiddleware = applyMiddleware(reduxRouterMiddleware)(createStore)
65
66const store = createStoreWithMiddleware(reducer)
67
68// Required for replaying actions from devtools to work
69reduxRouterMiddleware.listenForReplays(store)
70
71ReactDOM.render(
72 <Provider store={store}>
73 <Router history={history}>
74 <Route path="/" component={App}>
75 <Route path="foo" component={Foo}/>
76 <Route path="bar" component={Bar}/>
77 </Route>
78 </Router>
79 </Provider>,
80 document.getElementById('mount')
81)
82```
83
84Now you can read from `state.routing.location.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:
85
86```js
87import { routeActions } from 'redux-simple-router'
88
89function MyComponent({ dispatch }) {
90 return <Button onClick={() => dispatch(routeActions.push('/foo'))}/>;
91}
92```
93
94This 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 `UPDATE_LOCATION` constant that we provide:
95
96```js
97import { UPDATE_LOCATION } from 'redux-simple-router'
98
99function update(state, action) {
100 switch(action.type) {
101 case UPDATE_LOCATION:
102 // do something here
103 }
104}
105```
106
107### Examples
108
109* [examples/basic](https://github.com/jlongster/redux-simple-router/blob/master/examples/basic) - basic reference implementation
110
111Examples from the community:
112
113* [davezuko/react-redux-starter-kit](https://github.com/davezuko/react-redux-starter-kit) - popular redux starter kit
114 * **tip**: migrating from redux-router? use [this commit](https://github.com/davezuko/react-redux-starter-kit/commit/db66626ca8a02ecf030a3f7f5a669ac338fd5897) as a reference
115* [freeqaz/redux-simple-router-example](https://github.com/freeqaz/redux-simple-router-example) - example implementation
116* [choonkending/react-webpack-node](https://github.com/choonkending/react-webpack-node) - boilerplate for universal redux and react-router
117* [tj/frontend-boilerplate](https://github.com/tj/frontend-boilerplate)
118* [bdefore/universal-redux](https://github.com/bdefore/universal-redux) - npm package for universally rendered redux applications
119* [yangli1990/react-redux-isomorphic](https://github.com/yangli1990/Isomorphic-Universal-React-Template) - boilerplate for universal redux and redux-simple-router
120* [StevenIseki/redux-simple-router-example](https://github.com/StevenIseki/redux-simple-router-example)
121
122_Have an example to add? Send us a PR!_
123
124### API
125
126**This API is for an unreleased version. To view docs for 1.0.2, [click here](https://github.com/rackt/redux-simple-router/tree/1.0.2#api)**
127
128#### `syncHistory(history: History) => ReduxMiddleware`
129
130Call this to create a middleware that can be applied with Redux's `applyMiddleware` to allow actions to call history methods. The middleware will look for route actions created by `push`, `replace`, etc. and applies them to the history.
131
132#### `ReduxMiddleware.listenForReplays(store: ReduxStore, selectRouterState?: function)`
133
134By default, the syncing logic will not respond to replaying of actions, which means it won't work with projects like redux-devtools. Call this function on the middleware object returned from `syncHistory` and give it the store to listen to, and it will properly work with action replays. Obviously, you would do that after you have created the store and everything else has been set up.
135
136Supply an optional function `selectRouterState` to customize where to find the router state on your app state. It defaults to `state => state.routing`, so you would install the reducer under the name "routing". Feel free to change this to whatever you like.
137
138#### `ReduxMiddleware.unsubscribe()`
139
140Call this on the middleware returned from `syncHistory` to stop the syncing process set up by `listenForReplays`.
141
142#### `routeReducer`
143
144A reducer function that keeps track of the router state. You must to add this reducer to your app reducers when creating the store.
145
146#### `UPDATE_LOCATION`
147
148An action type that you can listen for in your reducers to be notified of route updates.
149
150#### `routeActions`
151
152An object that contains all the actions creators you can use to manipulate history:
153
154* `push(nextLocation: LocationDescriptor)`
155* `replace(nextLocation: LocationDescriptor)`
156* `go(n: number)`
157* `goForward()`
158* `goBack()`
159
160A [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).