diff --git a/modules/__tests__/Router-test.js b/modules/__tests__/Router-test.js index 3b3003a976..59996ef931 100644 --- a/modules/__tests__/Router-test.js +++ b/modules/__tests__/Router-test.js @@ -87,11 +87,11 @@ describe('Router', function () { location.pop(); expect(div.innerHTML).toMatch(/Bar/); }, Async.delay / 2); + }); - setTimeout(function () { - expect(div.innerHTML).toMatch(/Bar/); - done(); - }, Async.delay + 10); + steps.push(function () { + expect(div.innerHTML).toMatch(/Bar/); + done(); }); router = Router.create({ @@ -314,11 +314,11 @@ describe('Router', function () { location.pop(); expect(div.innerHTML).toMatch(/Bar/); }, RedirectToFooAsync.delay / 2); + }); - setTimeout(function () { - expect(div.innerHTML).toMatch(/Bar/); - done(); - }, RedirectToFooAsync.delay + 10); + steps.push(function () { + expect(div.innerHTML).toMatch(/Bar/); + done(); }); router = Router.create({ @@ -421,9 +421,14 @@ describe('Router', function () { var div = document.createElement('div'); + var runCount = 0; Router.run(routes, location, function (Handler) { + runCount += 1; React.render(, div, function () { - location.push('/abort'); + if (runCount === 1){ + location.push('/abort'); + return; + } expect(div.innerHTML).toMatch(/Foo/); expect(location.getCurrentPath()).toEqual('/foo'); done(); @@ -482,11 +487,11 @@ describe('Router', function () { location.pop(); expect(div.innerHTML).toMatch(/Bar/); }, Async.delay / 2); + }); - setTimeout(function () { - expect(div.innerHTML).toMatch(/Bar/); - done(); - }, Async.delay + 10); + steps.push(function () { + expect(div.innerHTML).toMatch(/Bar/); + done(); }); router = Router.create({ @@ -741,7 +746,8 @@ describe('Router', function () { Router.run(routes, location, function (Handler, state) { React.render(, div, function () { - location.push('/baz'); + if (state.path !== '/baz') + location.push('/baz'); }); }); }); diff --git a/modules/actions/LocationActions.js b/modules/actions/LocationActions.js index 68e512f769..3628151cb2 100644 --- a/modules/actions/LocationActions.js +++ b/modules/actions/LocationActions.js @@ -16,7 +16,12 @@ var LocationActions = { /** * Indicates the most recent entry should be removed from the history stack. */ - POP: 'pop' + POP: 'pop', + + /** + * Indicates the current location should be refreshed. + */ + REFRESH: 'refresh' }; diff --git a/modules/createRouter.js b/modules/createRouter.js index 833f5d2984..4e42012339 100644 --- a/modules/createRouter.js +++ b/modules/createRouter.js @@ -327,10 +327,6 @@ function createRouter(options) { Router.cancelPendingTransition(); var prevPath = state.path; - var isRefreshing = action == null; - - if (prevPath === path && !isRefreshing) - return; // Nothing to do! // Record the scroll position as early as possible to // get it before browsers try update it automatically. @@ -433,7 +429,7 @@ function createRouter(options) { }, refresh: function () { - Router.dispatch(location.getCurrentPath(), null); + Router.dispatch(location.getCurrentPath(), LocationActions.REFRESH); }, stop: function () { diff --git a/modules/locations/HashLocation.js b/modules/locations/HashLocation.js index a3ac0da6aa..610b08ab74 100644 --- a/modules/locations/HashLocation.js +++ b/modules/locations/HashLocation.js @@ -42,6 +42,11 @@ function onHashChange() { } } +function refresh() { + _actionType = LocationActions.REFRESH; + onHashChange(); +} + /** * A Location that uses `window.location.hash`. */ @@ -81,15 +86,25 @@ var HashLocation = { }, push(path) { - _actionType = LocationActions.PUSH; - window.location.hash = path; + // ensure change event if path has not changed + if (path !== HashLocation.getCurrentPath()) { + _actionType = LocationActions.PUSH; + window.location.hash = path; + } else { + refresh(); + } }, replace(path) { - _actionType = LocationActions.REPLACE; - window.location.replace( - window.location.pathname + window.location.search + '#' + path - ); + // ensure change event if path has not changed + if (path !== HashLocation.getCurrentPath()) { + _actionType = LocationActions.REPLACE; + window.location.replace( + window.location.pathname + window.location.search + '#' + path + ); + } else { + refresh(); + } }, pop() { diff --git a/modules/locations/HistoryLocation.js b/modules/locations/HistoryLocation.js index d08dfa34ed..5380e1252b 100644 --- a/modules/locations/HistoryLocation.js +++ b/modules/locations/HistoryLocation.js @@ -58,14 +58,24 @@ var HistoryLocation = { }, push(path) { - window.history.pushState({ path: path }, '', path); - History.length += 1; - notifyChange(LocationActions.PUSH); + // don't push state if path has not changed + if (path !== HistoryLocation.getCurrentPath()) { + window.history.pushState({ path: path }, '', path); + History.length += 1; + notifyChange(LocationActions.PUSH); + } else { + notifyChange(LocationActions.REFRESH); + } }, replace(path) { - window.history.replaceState({ path: path }, '', path); - notifyChange(LocationActions.REPLACE); + // don't replace state if path has not changed + if (path !== HistoryLocation.getCurrentPath()) { + window.history.replaceState({ path: path }, '', path); + notifyChange(LocationActions.REPLACE); + } else { + notifyChange(LocationActions.REFRESH); + } }, pop: History.back, diff --git a/modules/locations/TestLocation.js b/modules/locations/TestLocation.js index 76cab8ad65..143877f70d 100644 --- a/modules/locations/TestLocation.js +++ b/modules/locations/TestLocation.js @@ -42,9 +42,13 @@ class TestLocation { } push(path) { - this.history.push(path); - this._updateHistoryLength(); - this._notifyChange(LocationActions.PUSH); + if (!this.history.length || path !== this.getCurrentPath()) { + this.history.push(path); + this._updateHistoryLength(); + this._notifyChange(LocationActions.PUSH); + } else { + this._notifyChange(LocationActions.REFRESH); + } } replace(path) { @@ -53,9 +57,13 @@ class TestLocation { 'You cannot replace the current path with no history' ); - this.history[this.history.length - 1] = path; + if (path !== this.getCurrentPath()) { + this.history[this.history.length - 1] = path; + this._notifyChange(LocationActions.REPLACE); + } else { + this._notifyChange(LocationActions.REFRESH); + } - this._notifyChange(LocationActions.REPLACE); } pop() {