Skip to content

Commit

Permalink
[added] router.stop()
Browse files Browse the repository at this point in the history
This commit adds a router.stop() method that may be used to prevent
a router from listening to further changes to location. This method
is also called automatically when a router component is removed from
the DOM.

Thanks to @gaearon and @rpflorence for the initial thrust to get this
functionality into the router. This work doesn't entirely supercede remix-run#606,
but duplicates much of the work done there.
  • Loading branch information
mjackson committed Dec 29, 2014
1 parent 623af72 commit 75c6206
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 55 deletions.
39 changes: 17 additions & 22 deletions modules/locations/HashLocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,38 +67,33 @@ var HashLocation = {
// Do this BEFORE listening for hashchange.
ensureSlash();

if (_isListening)
return;
if (!_isListening) {
if (window.addEventListener) {
window.addEventListener('hashchange', onHashChange, false);
} else {
window.attachEvent('onhashchange', onHashChange);
}

if (window.addEventListener) {
window.addEventListener('hashchange', onHashChange, false);
} else {
window.attachEvent('onhashchange', onHashChange);
_isListening = true;
}

_isListening = true;
},

removeChangeListener: function(listener) {
for (var i = 0, l = _changeListeners.length; i < l; i ++) {
if (_changeListeners[i] === listener) {
_changeListeners.splice(i, 1);
break;
_changeListeners = _changeListeners.filter(function (l) {
return l !== listener;
});

if (_changeListeners.length === 0) {
if (window.removeEventListener) {
window.removeEventListener('hashchange', onHashChange, false);
} else {
window.removeEvent('onhashchange', onHashChange);
}
}

if (window.removeEventListener) {
window.removeEventListener('hashchange', onHashChange, false);
} else {
window.removeEvent('onhashchange', onHashChange);
}

if (_changeListeners.length === 0)
_isListening = false;
}
},



push: function (path) {
_actionType = LocationActions.PUSH;
window.location.hash = Path.encode(path);
Expand Down
39 changes: 17 additions & 22 deletions modules/locations/HistoryLocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,38 +38,33 @@ var HistoryLocation = {
addChangeListener: function (listener) {
_changeListeners.push(listener);

if (_isListening)
return;
if (!_isListening) {
if (window.addEventListener) {
window.addEventListener('popstate', onPopState, false);
} else {
window.attachEvent('popstate', onPopState);
}

if (window.addEventListener) {
window.addEventListener('popstate', onPopState, false);
} else {
window.attachEvent('popstate', onPopState);
_isListening = true;
}

_isListening = true;
},

removeChangeListener: function(listener) {
for (var i = 0, l = _changeListeners.length; i < l; i ++) {
if (_changeListeners[i] === listener) {
_changeListeners.splice(i, 1);
break;
_changeListeners = _changeListeners.filter(function (l) {
return l !== listener;
});

if (_changeListeners.length === 0) {
if (window.addEventListener) {
window.removeEventListener('popstate', onPopState);
} else {
window.removeEvent('popstate', onPopState);
}
}

if (window.addEventListener) {
window.removeEventListener('popstate', onPopState);
} else {
window.removeEvent('popstate', onPopState);
}

if (_changeListeners.length === 0)
_isListening = false;
}
},



push: function (path) {
window.history.pushState({ path: path }, '', Path.encode(path));
History.length += 1;
Expand Down
2 changes: 0 additions & 2 deletions modules/locations/TestLocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ var TestLocation = {
updateHistoryLength();
},

removeChangeListener: function () {},

push: function (path) {
TestLocation.history.push(path);
updateHistoryLength();
Expand Down
38 changes: 29 additions & 9 deletions modules/utils/createRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ function createRouter(options) {
var state = {};
var nextState = {};
var pendingTransition = null;
var changeListener = null;

function cancelPendingTransition() {
if (pendingTransition) {
pendingTransition.abort(new Cancellation);
pendingTransition = null;
}
}

function updateState() {
state = nextState;
Expand Down Expand Up @@ -192,6 +200,7 @@ function createRouter(options) {

defaultRoute: null,
notFoundRoute: null,
isRunning: false,

/**
* Adds routes to this router from the given children object (see ReactChildren).
Expand Down Expand Up @@ -317,10 +326,7 @@ function createRouter(options) {
* hooks wait, the transition is fully synchronous.
*/
dispatch: function (path, action, callback) {
if (pendingTransition) {
pendingTransition.abort(new Cancellation);
pendingTransition = null;
}
cancelPendingTransition();

var prevPath = state.path;
if (prevPath === path)
Expand Down Expand Up @@ -396,6 +402,11 @@ function createRouter(options) {
* Router.*Location objects (e.g. Router.HashLocation or Router.HistoryLocation).
*/
run: function (callback) {
invariant(
!this.isRunning,
'Router is already running'
);

var dispatchHandler = function (error, transition) {
pendingTransition = null;

Expand All @@ -412,7 +423,7 @@ function createRouter(options) {
router.dispatch(location, null, dispatchHandler);
} else {
// Listen for changes to the location.
var changeListener = function (change) {
changeListener = function (change) {
router.dispatch(change.path, change.type, dispatchHandler);
};

Expand All @@ -421,11 +432,20 @@ function createRouter(options) {

// Bootstrap using the current path.
router.dispatch(location.getCurrentPath(), null, dispatchHandler);

this.isRunning = true;
}
},

teardown: function() {
location.removeChangeListener(this.changeListener);
stop: function () {
cancelPendingTransition();

if (location.removeChangeListener && changeListener) {
location.removeChangeListener(changeListener);
changeListener = null;
}

this.isRunning = false;
}

},
Expand Down Expand Up @@ -461,8 +481,8 @@ function createRouter(options) {
this.setState(state);
},

componentWillUnmount: function() {
router.teardown();
componentWillUnmount: function () {
router.stop();
},

render: function () {
Expand Down

0 comments on commit 75c6206

Please sign in to comment.