react: Bug: element.current.scrollIntoView() not working as expected in chrome.
Hey 🙋♂️
I have built a simple chatbot using react, and when the user sends a message i want to show the last message in the chatWindow component, so I used the following code:
useEffect(
function () {
if (lastmessageRef.current !== null) {
lastmessageRef.current.scrollIntoView()
}
},
[lastmessageRef]
)
It works as expected in edge and Firefox, but on chrome it is behaving weird llink-to-the-chatbot: https://karthik2265.github.io/worlds-best-chatbot/ github-repo-link: https://github.com/karthik2265/worlds-best-chatbot
Thank you
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 14
- Comments: 22
A workaround I’ve found it to use
window.requestAnimationFrame:I had the same problem So I solved this by using setTimeout. (The flicker looks weird, but it works.)
Just wanted to shed some light into this issue and why it can probably be closed.
This has nothing to do with react. This is a problem that is related to the chromium implementation of the
scrollIntoViewmethod. There’s been some open issues for a long time in the chromium project regarding this issue.https://bugs.chromium.org/p/chromium/issues/detail?id=1121151 https://bugs.chromium.org/p/chromium/issues/detail?id=1043933 https://bugs.chromium.org/p/chromium/issues/detail?id=833617
So from what I’ve got from all the testing and searching the last few days is that chromium based browsers interrupt the
scrollIntoViewwhen any other scroll event is triggered.This only happens with the
scrollIntoViewmethod, thescrollToandscrollmethods don’t suffer from this issue. You can see and test this by yourself on the following fiddle.https://jsfiddle.net/2bnspw8e/8/
So then what’s a solution if you want to keep the simplicity of
scrollIntoViewand have other scroll happen at the same time?There is a ponyfill version of this method which reimplements it using the non broken
scrollmethod.I hope this clarifies what’s actually happening behind the scene and provides a solution while we all wait for a chromium fix.
For me it works if I remove the
behavior: 'smooth',prop, however, I really want the smooth scrolling behaviour 😦IMO almost all the answers above are not correct.
You are trying to invoke scrolling in
Effectbut it should be done inLayoutEffect.Function inside effect executes in parallel to DOM update commits and in 99% it will be invoked faster. So normally real DOM (according to the vDOM built up with your render function) is not ready yet at that point of time. This is why “workarounds” using
setTimeoutwork somehow. But usingLayoutEffectis more accurate.I’m having the same problem. scrollIntoView api doesn’t work inside useEffect, while it fires by onClick. Worth mentioning that it works in Firefox. Here is the code:
@hwangyena cool little thing I found out – you can do what you did
setTimeout(..., 0)and it works as well without delay, at least in my use case.It’s basically just a trick to defer until next tick in JS.
I had the same problem and managed to fix it by using the
scrollmethod for the parent node instead ofscrollIntoViewfor the children node:Works fine in Firefox, Chrome, Safari, Edge
https://user-images.githubusercontent.com/26645888/217844587-0b5d64d7-f34d-4128-8e43-9b7cefdc9403.mp4
@pjm4 Yeah, that was the case for me as well.
This is what I did as a workaround:
I want to know why this is happening
Note that
lastmessageRefas a dependency won’t do anything and can be removed. The effect won’t fire iflastmessageRef.currentchanges.Could you include a video of the behavior in Firefox and Chrome and explain with words what’s “weird” about this behavior? Also please include the exact version of those browsers and the operating system you’re using.
Bonus: Could you convert the repro into a codesandbox.io? Makes it easier to debug the issue.
Thanks for the digging and, I always wanted a one-trick pony!
This shows up at just the right time!
Cheers!