Reputation: 3
I'm building a react single page app and have noticed that the scrollIntoView function does not work on chrome based browsers (tested on edge&chrome) when the component is out of focus. I have a long async operation that involves waiting on a server response. When that response arrives, some elements are being created and the page should scroll them into view. Losing focus causes the scrolling operation to fail.
useEffect(() => {
const onFocus = () => {
console.log('gained focus')
}
const onBlur = () => {
console.log('lost focus: ', currentStage)
}
window.addEventListener('focus', onFocus)
window.addEventListener('blur', onBlur)
return () => {
window.removeEventListener('focus', onFocus)
window.removeEventListener('blur', onBlur)
}
}, [])
I use this for debugging purposes ^ and this is the actual scroll logic:
useLayoutEffect(() => {
attemptScroll()
return () => {
clearTimeout(scrollEndTimer.current)
}
}, [currentStage, activeStages])
(the stage changes upon server response)
const attemptScroll = () => {
console.log(`current stage: ${currentStage.name}`)
if (!scrollerRef.current) return
const stageElement = document.getElementById(currentStage?.name)
if (!stageElement) {
console.error(`Stage ${currentStage?.name} was not found in the DOM`)
console.error(currentStage)
return
}
console.log('scrolling to element:', stageElement.current)
setScrolling(true)
stageElement.focus()
stageElement.scrollIntoView({
behavior: 'smooth',
block: 'start',
inline: 'start'
})
const checkScrollCompletion = callback => {
clearTimeout(scrollEndTimer.current)
const lastScrollLeft = scrollerRef.current.scrollLeft
scrollEndTimer.current = setTimeout(() => {
const currentScrollLeft = scrollerRef.current.scrollLeft
if (currentScrollLeft === lastScrollLeft) {
callback()
} else {
checkScrollCompletion(callback)
}
}, 100)
}
setScrolling(false)
}
Just to make is super clear:
Even the 'scrolling to element' log statement is being written, with the correct element. Everything works as intended, except for the scroll.
I could technically work around this by making the page attempt scrolling when the component returns to focus, but even after if I ignore the UX hit, I noticed the it loses focus on mobile even when the browser is still open on the screen, so just randomly tapping the screen until something happens is a no go.
Does anybody know why and how can I fix this?
Thanks
Upvotes: 0
Views: 86