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

Commit 5e41803

Browse files
committed
Handle routing state and replace
1 parent 40c57bb commit 5e41803

File tree

3 files changed

+155
-51
lines changed

3 files changed

+155
-51
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,8 @@
3636
"isparta": "^4.0.0",
3737
"mocha": "^2.3.4",
3838
"redux": "^3.0.4"
39+
},
40+
"dependencies": {
41+
"deep-equal": "^1.0.1"
3942
}
4043
}

src/index.js

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
1+
const deepEqual = require('deep-equal');
12

2-
// constants
3+
// Constants
34

45
const UPDATE_PATH = "@@router/UPDATE_PATH";
56
const SELECT_STATE = state => state.routing;
67

78
// Action creator
89

9-
function updatePath(path, avoidRouterUpdate) {
10+
function pushPath(path, state, avoidRouterUpdate) {
1011
return {
1112
type: UPDATE_PATH,
1213
path: path,
14+
state: state,
15+
replace: false,
16+
avoidRouterUpdate: !!avoidRouterUpdate
17+
};
18+
}
19+
20+
function replacePath(path, state, avoidRouterUpdate) {
21+
return {
22+
type: UPDATE_PATH,
23+
path: path,
24+
state: state,
25+
replace: true,
1326
avoidRouterUpdate: !!avoidRouterUpdate
1427
}
1528
}
@@ -18,25 +31,27 @@ function updatePath(path, avoidRouterUpdate) {
1831

1932
const initialState = {
2033
changeId: 1,
21-
path: (typeof window !== 'undefined') ?
22-
locationToString(window.location) :
23-
'/'
34+
path: undefined,
35+
state: undefined,
36+
replace: false
2437
};
2538

2639
function update(state=initialState, action) {
2740
if(action.type === UPDATE_PATH) {
2841
return Object.assign({}, state, {
2942
path: action.path,
30-
changeId: state.changeId + (action.avoidRouterUpdate ? 0 : 1)
43+
changeId: state.changeId + (action.avoidRouterUpdate ? 0 : 1),
44+
state: action.state,
45+
replace: action.replace
3146
});
3247
}
3348
return state;
3449
}
3550

3651
// Syncing
3752

38-
function locationToString(location) {
39-
return location.pathname + location.search + location.hash;
53+
function locationsAreEqual(a, b) {
54+
return a.path === b.path && deepEqual(a.state, b.state);
4055
}
4156

4257
function syncReduxAndRouter(history, store, selectRouterState = SELECT_STATE) {
@@ -50,25 +65,36 @@ function syncReduxAndRouter(history, store, selectRouterState = SELECT_STATE) {
5065
);
5166
}
5267

68+
let historyLocation = {};
69+
5370
const unsubscribeHistory = history.listen(location => {
54-
const routePath = locationToString(location);
71+
historyLocation = {
72+
path: history.createPath(location),
73+
state: location.state
74+
};
75+
76+
const routing = getRouterState();
77+
78+
// Avoid dispatching an action if the store is already up-to-date,
79+
// even if `history` wouldn't do anything if the location is the same
80+
if(locationsAreEqual(routing, historyLocation)) return;
5581

56-
// Avoid dispatching an action if the store is already up-to-date
57-
if(getRouterState().path !== routePath) {
58-
store.dispatch(updatePath(routePath, { avoidRouterUpdate: true }));
59-
}
82+
store.dispatch(pushPath(historyLocation.path, historyLocation.state, { avoidRouterUpdate: true }));
6083
});
6184

6285
const unsubscribeStore = store.subscribe(() => {
6386
const routing = getRouterState();
6487

65-
// Only update the router once per `updatePath` call. This is
88+
// Only update the router once per `pushPath` call. This is
6689
// indicated by the `changeId` state; when that number changes, we
67-
// should call `pushState`.
68-
if(lastChangeId !== routing.changeId) {
69-
lastChangeId = routing.changeId;
70-
history.pushState(null, routing.path);
71-
}
90+
// should update the history.
91+
if(lastChangeId === routing.changeId) return;
92+
93+
lastChangeId = routing.changeId;
94+
95+
const method = routing.replace ? 'replaceState' : 'pushState';
96+
97+
history[method](routing.state, routing.path);
7298
});
7399

74100
return function unsubscribe() {
@@ -79,7 +105,8 @@ function syncReduxAndRouter(history, store, selectRouterState = SELECT_STATE) {
79105

80106
module.exports = {
81107
UPDATE_PATH,
82-
updatePath,
108+
pushPath,
109+
replacePath,
83110
syncReduxAndRouter,
84111
routeReducer: update
85112
};

0 commit comments

Comments
 (0)