Skip to content

Commit 47a6329

Browse files
committed
Fix scroll position history enhancers
1 parent d7bdd87 commit 47a6329

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

modules/useScrollToTopBehavior.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ export default function useScrollToTopBehavior(createHistory) {
44
return function (options) {
55
const history = createHistory(options)
66

7-
history.listen(function (location) {
8-
if (location.action === 'POP') {
9-
return
10-
}
11-
12-
setWindowScrollPosition(0, 0)
7+
history.listen(() => {
8+
// Need to defer this to after other listeners fire in case some of them
9+
// update the page.
10+
setTimeout(() => setWindowScrollPosition(0, 0))
1311
})
1412

1513
return history

modules/useStandardScrollBehavior.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { readState, saveState } from 'history/lib/DOMStateStorage'
2+
import { addEventListener, getWindowScrollPosition, setWindowScrollPosition }
3+
from './DOMUtils'
4+
5+
export default function useStandardScrollBehavior(createHistory) {
6+
return function (options) {
7+
const history = createHistory(options)
8+
9+
let currentLocation
10+
let savePositionHandle = null
11+
12+
addEventListener(window, 'scroll', () => {
13+
if (savePositionHandle !== null) {
14+
clearTimeout(savePositionHandle)
15+
}
16+
17+
savePositionHandle = setTimeout(() => {
18+
savePositionHandle = null
19+
20+
if (!currentLocation) {
21+
return
22+
}
23+
const { key } = currentLocation
24+
25+
const state = readState(key)
26+
saveState(key, {
27+
...state, scrollPosition: getWindowScrollPosition()
28+
})
29+
})
30+
})
31+
32+
history.listenBefore(() => {
33+
if (savePositionHandle !== null) {
34+
clearTimeout(savePositionHandle)
35+
savePositionHandle = null
36+
}
37+
})
38+
39+
function getScrollPosition() {
40+
const state = readState(currentLocation.key)
41+
if (!state) {
42+
return null
43+
}
44+
45+
return state.scrollPosition
46+
}
47+
48+
history.listen(location => {
49+
currentLocation = location
50+
51+
const scrollPosition = getScrollPosition() || {}
52+
const { x = 0, y = 0 } = scrollPosition
53+
54+
// Need to defer the scroll operation because this listener fires before
55+
// e.g. the router updates its state, and this might need to scroll past
56+
// the end of the page pre-transition if the popped page was longer.
57+
setTimeout(() => setWindowScrollPosition(x, y))
58+
})
59+
60+
return history
61+
}
62+
}

0 commit comments

Comments
 (0)