@@ -55,12 +55,26 @@ function update(state=initialState, { type, payload }) {
55
55
// Syncing
56
56
57
57
function locationsAreEqual ( a , b ) {
58
- return a . path === b . path && deepEqual ( a . state , b . state ) ;
58
+ return a != null && b != null && a . path === b . path && deepEqual ( a . state , b . state ) ;
59
59
}
60
60
61
61
function syncReduxAndRouter ( history , store , selectRouterState = SELECT_STATE ) {
62
62
const getRouterState = ( ) => selectRouterState ( store . getState ( ) ) ;
63
- let lastChangeId = 0 ;
63
+
64
+ // Because we're not able to set the initial path in `initialState` we need a
65
+ // "hack" to get "Revert" in Redux DevTools to work. We solve this by keeping
66
+ // the first route so we can revert to this route when the initial state is
67
+ // replayed to reset the state. Basically, we treat the first route as our
68
+ // initial state.
69
+ let firstRoute = undefined ;
70
+
71
+ // To properly handle store updates we need to track the last route. This
72
+ // route contains a `changeId` which is updated on every `pushPath` and
73
+ // `replacePath`. If this id changes we always trigger a history update.
74
+ // However, if the id does not change, we check if the location has changed,
75
+ // and if it is we trigger a history update. (If these are out of sync it's
76
+ // likely because of React DevTools.)
77
+ let lastRoute = undefined ;
64
78
65
79
if ( ! getRouterState ( ) ) {
66
80
throw new Error (
@@ -75,6 +89,10 @@ function syncReduxAndRouter(history, store, selectRouterState = SELECT_STATE) {
75
89
state : location . state
76
90
} ;
77
91
92
+ if ( firstRoute === undefined ) {
93
+ firstRoute = route ;
94
+ }
95
+
78
96
// Avoid dispatching an action if the store is already up-to-date,
79
97
// even if `history` wouldn't do anything if the location is the same
80
98
if ( locationsAreEqual ( getRouterState ( ) , route ) ) return ;
@@ -87,14 +105,18 @@ function syncReduxAndRouter(history, store, selectRouterState = SELECT_STATE) {
87
105
} ) ;
88
106
89
107
const unsubscribeStore = store . subscribe ( ( ) => {
90
- const routing = getRouterState ( ) ;
108
+ let routing = getRouterState ( ) ;
91
109
92
- // Only update the router once per `pushPath` call. This is
93
- // indicated by the `changeId` state; when that number changes, we
94
- // should update the history.
95
- if ( lastChangeId === routing . changeId ) return ;
110
+ // Treat `firstRoute` as our `initialState`
111
+ if ( routing === initialState ) {
112
+ routing = firstRoute ;
113
+ }
114
+
115
+ if ( lastRoute !== undefined && lastRoute . changeId === routing . changeId ) {
116
+ if ( locationsAreEqual ( routing , lastRoute ) ) return ;
117
+ }
96
118
97
- lastChangeId = routing . changeId ;
119
+ lastRoute = routing ;
98
120
99
121
const method = routing . replace ? 'replaceState' : 'pushState' ;
100
122
0 commit comments