Skip to content

Commit 0dce2e9

Browse files
committed
Port ignoreScrollBehavior from #388 to the new API
1 parent f05e49d commit 0dce2e9

File tree

4 files changed

+112
-112
lines changed

4 files changed

+112
-112
lines changed

modules/__tests__/Router-test.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,90 @@ describe('Router.run', function () {
346346
});
347347
});
348348

349+
describe('ignoreScrollBehavior', function () {
350+
var routes = (
351+
<Route handler={Nested}>
352+
<Route handler={Foo} ignoreScrollBehavior>
353+
<Route handler={Foo} path='/feed' />
354+
<Route handler={Foo} path='/discover' />
355+
</Route>
356+
<Route path='/search' handler={Foo} ignoreScrollBehavior />
357+
<Route path='/about' handler={Foo} />
358+
</Route>
359+
);
360+
361+
var div, didUpdateScroll;
362+
beforeEach(function (done) {
363+
TestLocation.history = [ '/feed' ];
364+
365+
div = document.createElement('div');
366+
document.body.appendChild(div);
367+
368+
var MockScrollBehavior = {
369+
updateScrollPosition() {
370+
didUpdateScroll = true;
371+
}
372+
};
373+
374+
Router.create({
375+
routes: routes,
376+
location: TestLocation,
377+
scrollBehavior: MockScrollBehavior
378+
}).run(function (Handler) {
379+
React.render(<Handler/>, div, function () {
380+
done();
381+
});
382+
});
383+
});
384+
385+
afterEach(function () {
386+
div.parentNode.removeChild(div);
387+
didUpdateScroll = false;
388+
});
389+
390+
it('calls updateScroll the first time', function () {
391+
expect(didUpdateScroll).toBe(true);
392+
});
393+
394+
describe('decides whether to update scroll on transition', function () {
395+
beforeEach(function () {
396+
didUpdateScroll = false;
397+
});
398+
399+
afterEach(function () {
400+
TestLocation.pop();
401+
});
402+
403+
it('calls updateScroll when no ancestors ignore scroll', function () {
404+
TestLocation.push('/about');
405+
expect(didUpdateScroll).toBe(true);
406+
});
407+
408+
it('calls updateScroll when no ancestors ignore scroll although source and target do', function () {
409+
TestLocation.push('/search');
410+
expect(didUpdateScroll).toBe(true);
411+
});
412+
413+
it('calls updateScroll when source is same as target and does not ignore scroll', function () {
414+
TestLocation.push('/about?page=2');
415+
expect(didUpdateScroll).toBe(true);
416+
});
417+
418+
it('does not call updateScroll when common ancestor ignores scroll', function () {
419+
TestLocation.push('/discover');
420+
expect(didUpdateScroll).toBe(false);
421+
});
422+
423+
it('does not call updateScroll when source is same as target and ignores scroll', function () {
424+
TestLocation.push('/search');
425+
didUpdateScroll = false;
426+
427+
TestLocation.push('/search?q=test');
428+
expect(didUpdateScroll).toBe(false);
429+
});
430+
});
431+
});
432+
349433
describe('makePath', function () {
350434
var router;
351435
beforeEach(function () {

modules/components/__tests__/Routes-test.js

Lines changed: 0 additions & 109 deletions
This file was deleted.

modules/mixins/Scrolling.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@ var invariant = require('react/lib/invariant');
22
var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM;
33
var getWindowScrollPosition = require('../utils/getWindowScrollPosition');
44

5+
function shouldUpdateScroll(state, prevState) {
6+
if (!prevState) {
7+
return true;
8+
}
9+
10+
var routes = state.routes;
11+
var prevRoutes = prevState.routes;
12+
13+
var sharedAncestorRoutes = routes.filter(function (route) {
14+
return prevRoutes.indexOf(route) !== -1;
15+
});
16+
17+
return !sharedAncestorRoutes.some(function (route) {
18+
return route.ignoreScrollBehavior;
19+
});
20+
}
21+
522
/**
623
* Provides the router with the ability to manage window scroll position
724
* according to its scroll behavior.
@@ -25,8 +42,8 @@ var Scrolling = {
2542
this._scrollHistory[this.state.path] = getWindowScrollPosition();
2643
},
2744

28-
componentDidUpdate: function () {
29-
this._updateScroll();
45+
componentDidUpdate: function (prevProps, prevState) {
46+
this._updateScroll(prevState);
3047
},
3148

3249
componentWillUnmount: function () {
@@ -40,7 +57,11 @@ var Scrolling = {
4057
return this._scrollHistory[path] || null;
4158
},
4259

43-
_updateScroll: function () {
60+
_updateScroll: function (prevState) {
61+
if (!shouldUpdateScroll(this.state, prevState)) {
62+
return;
63+
}
64+
4465
var scrollBehavior = this.getScrollBehavior();
4566

4667
if (scrollBehavior)

modules/utils/createRoutesFromChildren.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ function createRoute(element, parentRoute, namedRoutes) {
5555

5656
var route = { name: props.name };
5757

58+
if (props.ignoreScrollBehavior) {
59+
route.ignoreScrollBehavior = true;
60+
}
61+
5862
if (type === Redirect.type) {
5963
route.handler = createRedirectHandler(props.to, props.params, props.query);
6064
props.path = props.path || props.from || '*';

0 commit comments

Comments
 (0)