Skip to content

Commit

Permalink
Merge pull request remix-run#667 from taurose/master
Browse files Browse the repository at this point in the history
Ignore stale transitions
  • Loading branch information
mjackson committed Jan 9, 2015
2 parents 106e904 + 1f81286 commit 12be8e1
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 3 deletions.
114 changes: 114 additions & 0 deletions modules/__tests__/Router-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,66 @@ describe('Router', function () {
});
});
});

it('stops waiting on router.transitionTo after another asynchronous transition ended ', function (done) {
var LongAsync = React.createClass({
statics: {
delay: Async.delay * 2,

willTransitionTo: function (transition, params, query, callback) {
setTimeout(callback, this.delay);
}
},

render: function () {
return <div className="Async2">Async2</div>;
}
});

TestLocation.history = [ '/foo' ];
var routes = [
<Route handler={Foo} path='/foo' />,
<Route handler={Bar} path='/bar' />,
<Route handler={Async} path='/async1' />,
<Route handler={LongAsync} path='/async2' />
];

var div = document.createElement('div');
var steps = [];
var router = Router.create({
routes: routes,
location: TestLocation
});

steps.push(function () {
router.transitionTo('/async1');
setTimeout(function () {
router.transitionTo('/async2');
expect(div.innerHTML).toMatch(/Foo/);
setTimeout(function () {
expect(div.innerHTML).toMatch(/Foo/);
router.transitionTo('/bar');
expect(div.innerHTML).toMatch(/Bar/);
}, Async.delay);
}, Async.delay / 2);
});

steps.push(function () {
setTimeout(function () {
expect(div.innerHTML).toMatch(/Bar/);
done();
}, Async.delay);
});

steps.push(function () {
});

router.run(function (Handler, state) {
React.render(<Handler />, div, function () {
steps.shift()();
});
});
});
});

describe('transition.redirect', function () {
Expand Down Expand Up @@ -521,6 +581,60 @@ describe('Router', function () {
});
});
});

it('ignores aborting asynchronously in willTransitionTo when aborted before router.transitionTo', function (done) {
var AbortAsync2 = React.createClass({
statics: {
willTransitionTo: function (transition, params, query, callback) {
transition.abort();
setTimeout(callback, Async.delay);
}
},

render: function () {
return <div>Abort</div>;
}
});

TestLocation.history = [ '/foo' ];
var routes = [
<Route handler={Foo} path='/foo' />,
<Route handler={Bar} path='/bar' />,
<Route handler={AbortAsync2} path='/abort' />
];

var div = document.createElement('div');
var steps = [];
var router = Router.create({
routes: routes,
location: TestLocation
});

steps.push(function () {
router.transitionTo('/abort');
expect(div.innerHTML).toMatch(/Foo/);

router.transitionTo('/bar');
expect(div.innerHTML).toMatch(/Bar/);
});

steps.push(function () {
setTimeout(function () {
expect(div.innerHTML).toMatch(/Bar/);
expect(TestLocation.history).toEqual(['/foo', '/bar']);
done();
}, Async.delay + 10);
});

steps.push(function () {
});

router.run(function (Handler, state) {
React.render(<Handler />, div, function () {
steps.shift()();
});
});
});
});
});

Expand Down
10 changes: 7 additions & 3 deletions modules/utils/createRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,15 @@ function createRouter(options) {
);

var dispatchHandler = function (error, transition) {
if (error)
onError.call(router, error);

if (pendingTransition !== transition)
return;

pendingTransition = null;

if (error) {
onError.call(router, error);
} else if (transition.isAborted) {
if (transition.isAborted) {
onAbort.call(router, transition.abortReason, location);
} else {
callback.call(router, router, nextState);
Expand Down

0 comments on commit 12be8e1

Please sign in to comment.