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

Commit 8a8654f

Browse files
committed
Merge pull request #83 from jlongster/init-action
Refactor initialization logic
2 parents 1c75327 + 0ef4fd3 commit 8a8654f

File tree

1 file changed

+44
-29
lines changed

1 file changed

+44
-29
lines changed

src/index.js

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,23 @@ const deepEqual = require('deep-equal');
22

33
// Constants
44

5+
const INIT_PATH = "@@router/INIT_PATH";
56
const UPDATE_PATH = "@@router/UPDATE_PATH";
67
const SELECT_STATE = state => state.routing;
78

8-
// Action creator
9+
// Action creators
10+
11+
function initPath(path, state) {
12+
return {
13+
type: INIT_PATH,
14+
payload: {
15+
path: path,
16+
state: state,
17+
replace: false,
18+
avoidRouterUpdate: true
19+
}
20+
};
21+
}
922

1023
function pushPath(path, state, { avoidRouterUpdate = false } = {}) {
1124
return {
@@ -33,15 +46,15 @@ function replacePath(path, state, { avoidRouterUpdate = false } = {}) {
3346

3447
// Reducer
3548

36-
const initialState = {
49+
let initialState = {
3750
changeId: 1,
3851
path: undefined,
3952
state: undefined,
4053
replace: false
4154
};
4255

4356
function update(state=initialState, { type, payload }) {
44-
if(type === UPDATE_PATH) {
57+
if(type === INIT_PATH || type === UPDATE_PATH) {
4558
return Object.assign({}, state, {
4659
path: payload.path,
4760
changeId: state.changeId + (payload.avoidRouterUpdate ? 0 : 1),
@@ -61,16 +74,6 @@ function locationsAreEqual(a, b) {
6174
function syncReduxAndRouter(history, store, selectRouterState = SELECT_STATE) {
6275
const getRouterState = () => selectRouterState(store.getState());
6376

64-
// `initialState` *sould* represent the current location when the
65-
// app loads, but we cannot get the current location when it is
66-
// defined. What happens is `history.listen` is called immediately
67-
// when it is registered, and it updates the app state with an
68-
// action. This causes problems with redux devtools because "revert"
69-
// will use `initialState` and it won't revert to the original URL.
70-
// Instead, we track the first route and hack it to load when using
71-
// the `initialState`.
72-
let firstRoute = undefined;
73-
7477
// To properly handle store updates we need to track the last route.
7578
// This route contains a `changeId` which is updated on every
7679
// `pushPath` and `replacePath`. If this id changes we always
@@ -93,14 +96,32 @@ function syncReduxAndRouter(history, store, selectRouterState = SELECT_STATE) {
9396
state: location.state
9497
};
9598

96-
if (firstRoute === undefined) {
97-
firstRoute = route;
98-
}
99-
100-
// Avoid dispatching an action if the store is already up-to-date,
101-
// even if `history` wouldn't do anything if the location is the
102-
// same
103-
if(!locationsAreEqual(getRouterState(), route)) {
99+
if (!lastRoute) {
100+
// `initialState` *should* represent the current location when
101+
// the app loads, but we cannot get the current location when it
102+
// is defined. What happens is `history.listen` is called
103+
// immediately when it is registered, and it updates the app
104+
// state with an UPDATE_PATH action. This causes problem when
105+
// users are listening to UPDATE_PATH actions just for
106+
// *changes*, and with redux devtools because "revert" will use
107+
// `initialState` and it won't revert to the original URL.
108+
// Instead, we specialize the first route notification and do
109+
// different things based on it.
110+
initialState = {
111+
changeId: 1,
112+
path: route.path,
113+
state: route.state,
114+
replace: false
115+
};
116+
117+
// Also set `lastRoute` so that the store subscriber doesn't
118+
// trigger an unnecessary `pushState` on load
119+
lastRoute = initialState;
120+
121+
store.dispatch(initPath(route.path, route.state));
122+
} else if(!locationsAreEqual(getRouterState(), route)) {
123+
// The above check avoids dispatching an action if the store is
124+
// already up-to-date
104125
const method = location.action === 'REPLACE' ? replacePath : pushPath;
105126
store.dispatch(method(route.path, route.state, { avoidRouterUpdate: true }));
106127
}
@@ -109,15 +130,9 @@ function syncReduxAndRouter(history, store, selectRouterState = SELECT_STATE) {
109130
const unsubscribeStore = store.subscribe(() => {
110131
let routing = getRouterState();
111132

112-
// Treat `firstRoute` as our `initialState`
113-
if(routing === initialState) {
114-
routing = firstRoute;
115-
}
116-
117-
// Only trigger history update is this is a new change or the
133+
// Only trigger history update if this is a new change or the
118134
// location has changed.
119-
if(lastRoute === undefined ||
120-
lastRoute.changeId !== routing.changeId ||
135+
if(lastRoute.changeId !== routing.changeId ||
121136
!locationsAreEqual(lastRoute, routing)) {
122137

123138
lastRoute = routing;

0 commit comments

Comments
 (0)