Skip to content

Commit

Permalink
Fix scroll position history enhancers
Browse files Browse the repository at this point in the history
  • Loading branch information
taion committed Nov 4, 2015
1 parent d7bdd87 commit 47a6329
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 6 deletions.
10 changes: 4 additions & 6 deletions modules/useScrollToTopBehavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ export default function useScrollToTopBehavior(createHistory) {
return function (options) {
const history = createHistory(options)

history.listen(function (location) {
if (location.action === 'POP') {
return
}

setWindowScrollPosition(0, 0)
history.listen(() => {
// Need to defer this to after other listeners fire in case some of them
// update the page.
setTimeout(() => setWindowScrollPosition(0, 0))
})

return history
Expand Down
62 changes: 62 additions & 0 deletions modules/useStandardScrollBehavior.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { readState, saveState } from 'history/lib/DOMStateStorage'
import { addEventListener, getWindowScrollPosition, setWindowScrollPosition }
from './DOMUtils'

export default function useStandardScrollBehavior(createHistory) {
return function (options) {
const history = createHistory(options)

let currentLocation
let savePositionHandle = null

addEventListener(window, 'scroll', () => {
if (savePositionHandle !== null) {
clearTimeout(savePositionHandle)
}

savePositionHandle = setTimeout(() => {
savePositionHandle = null

if (!currentLocation) {
return
}
const { key } = currentLocation

const state = readState(key)
saveState(key, {
...state, scrollPosition: getWindowScrollPosition()
})
})
})

history.listenBefore(() => {
if (savePositionHandle !== null) {
clearTimeout(savePositionHandle)
savePositionHandle = null
}
})

function getScrollPosition() {
const state = readState(currentLocation.key)
if (!state) {
return null
}

return state.scrollPosition
}

history.listen(location => {
currentLocation = location

const scrollPosition = getScrollPosition() || {}
const { x = 0, y = 0 } = scrollPosition

// Need to defer the scroll operation because this listener fires before
// e.g. the router updates its state, and this might need to scroll past
// the end of the page pre-transition if the popped page was longer.
setTimeout(() => setWindowScrollPosition(x, y))
})

return history
}
}

0 comments on commit 47a6329

Please sign in to comment.