Skip to content

Commit 12be8e1

Browse files
committed
Merge pull request #667 from taurose/master
Ignore stale transitions
2 parents 106e904 + 1f81286 commit 12be8e1

File tree

2 files changed

+121
-3
lines changed

2 files changed

+121
-3
lines changed

modules/__tests__/Router-test.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,66 @@ describe('Router', function () {
186186
});
187187
});
188188
});
189+
190+
it('stops waiting on router.transitionTo after another asynchronous transition ended ', function (done) {
191+
var LongAsync = React.createClass({
192+
statics: {
193+
delay: Async.delay * 2,
194+
195+
willTransitionTo: function (transition, params, query, callback) {
196+
setTimeout(callback, this.delay);
197+
}
198+
},
199+
200+
render: function () {
201+
return <div className="Async2">Async2</div>;
202+
}
203+
});
204+
205+
TestLocation.history = [ '/foo' ];
206+
var routes = [
207+
<Route handler={Foo} path='/foo' />,
208+
<Route handler={Bar} path='/bar' />,
209+
<Route handler={Async} path='/async1' />,
210+
<Route handler={LongAsync} path='/async2' />
211+
];
212+
213+
var div = document.createElement('div');
214+
var steps = [];
215+
var router = Router.create({
216+
routes: routes,
217+
location: TestLocation
218+
});
219+
220+
steps.push(function () {
221+
router.transitionTo('/async1');
222+
setTimeout(function () {
223+
router.transitionTo('/async2');
224+
expect(div.innerHTML).toMatch(/Foo/);
225+
setTimeout(function () {
226+
expect(div.innerHTML).toMatch(/Foo/);
227+
router.transitionTo('/bar');
228+
expect(div.innerHTML).toMatch(/Bar/);
229+
}, Async.delay);
230+
}, Async.delay / 2);
231+
});
232+
233+
steps.push(function () {
234+
setTimeout(function () {
235+
expect(div.innerHTML).toMatch(/Bar/);
236+
done();
237+
}, Async.delay);
238+
});
239+
240+
steps.push(function () {
241+
});
242+
243+
router.run(function (Handler, state) {
244+
React.render(<Handler />, div, function () {
245+
steps.shift()();
246+
});
247+
});
248+
});
189249
});
190250

191251
describe('transition.redirect', function () {
@@ -521,6 +581,60 @@ describe('Router', function () {
521581
});
522582
});
523583
});
584+
585+
it('ignores aborting asynchronously in willTransitionTo when aborted before router.transitionTo', function (done) {
586+
var AbortAsync2 = React.createClass({
587+
statics: {
588+
willTransitionTo: function (transition, params, query, callback) {
589+
transition.abort();
590+
setTimeout(callback, Async.delay);
591+
}
592+
},
593+
594+
render: function () {
595+
return <div>Abort</div>;
596+
}
597+
});
598+
599+
TestLocation.history = [ '/foo' ];
600+
var routes = [
601+
<Route handler={Foo} path='/foo' />,
602+
<Route handler={Bar} path='/bar' />,
603+
<Route handler={AbortAsync2} path='/abort' />
604+
];
605+
606+
var div = document.createElement('div');
607+
var steps = [];
608+
var router = Router.create({
609+
routes: routes,
610+
location: TestLocation
611+
});
612+
613+
steps.push(function () {
614+
router.transitionTo('/abort');
615+
expect(div.innerHTML).toMatch(/Foo/);
616+
617+
router.transitionTo('/bar');
618+
expect(div.innerHTML).toMatch(/Bar/);
619+
});
620+
621+
steps.push(function () {
622+
setTimeout(function () {
623+
expect(div.innerHTML).toMatch(/Bar/);
624+
expect(TestLocation.history).toEqual(['/foo', '/bar']);
625+
done();
626+
}, Async.delay + 10);
627+
});
628+
629+
steps.push(function () {
630+
});
631+
632+
router.run(function (Handler, state) {
633+
React.render(<Handler />, div, function () {
634+
steps.shift()();
635+
});
636+
});
637+
});
524638
});
525639
});
526640

modules/utils/createRouter.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,15 @@ function createRouter(options) {
410410
);
411411

412412
var dispatchHandler = function (error, transition) {
413+
if (error)
414+
onError.call(router, error);
415+
416+
if (pendingTransition !== transition)
417+
return;
418+
413419
pendingTransition = null;
414420

415-
if (error) {
416-
onError.call(router, error);
417-
} else if (transition.isAborted) {
421+
if (transition.isAborted) {
418422
onAbort.call(router, transition.abortReason, location);
419423
} else {
420424
callback.call(router, router, nextState);

0 commit comments

Comments
 (0)