3

I have a scrollable content and we could see our scrollbar appear when we keep inserting new data. I want to position the scrollbar always at the bottom in order to avoid scrolling manually. If you take Messenger for an example, when you type a message and submit it, our scroll height increases, but the scroll doesn't move up and down.

I tried to do the same using the following technique:

const App = () => {
    const myRef = useRef<HTMLDivElement>(null)

    const [msgs, setMsgs] = useState<string[]>([])
    const [text, setText] = useState<string>("")

    const scrollToMyRef = () => {
        if (myRef.current) {
            myRef.current.scrollTop = myRef.current.scrollHeight
        }
    };

    const handleInput = (e: React.KeyboardEvent<HTMLInputElement>) => {
        if (e.key === 'Enter') {
            // setText('')
            setMsgs(prevState => [...prevState, text])
        }
    }

    useEffect(() => {
        scrollToMyRef()
    }, [msgs])

    return (
        <div className="app">
            <div className="container" ref={myRef}>
                <div className={"messages-list"}>
                    {
                        msgs.map((msg, i) => (
                            <div key={i}>{msg}</div>
                        ))
                    }
                </div>
                <div className="form">
                    <input
                        type={"text"}
                        onKeyPress={e => handleInput(e)}
                        value={text}
                        onChange={(e) => setText(e.target.value)}
                    />
                    <input type={"button"} value={"add"} />
                </div>
            </div>
        </div>
    );
} 

The problem is that our scroll moves up and down, causing the content to "blink/flicker". Why exactly does this happen?

I have also tried scrollIntoView but it does not provide the desired output as well.

Here's a sandbox to reproduce the problem: https://kfkx5.csb.app/

Nick
  • 169
  • 1
  • 10

1 Answers1

1

[Edit]: I just found this codePen. It does exactly what you are looking for :)


I guess what you are looking for is :

window.scrollTo(0,document.body.scrollHeight);

instead of :

myRef.current.scrollTop = myRef.current.scrollHeight;

Of course, you need to change document.body.scrollHeight by the scrollable block. You can probably clean up a bit of code if your refs aren't used for anything else.

Here is the repro on Stackblitz. I only changed the line above from your own code.

P.S. : I got this answer from this SO thread :)

Quentin Grisel
  • 4,794
  • 1
  • 10
  • 15
  • I tried it, but if you look closer, you could see that the scrollbar is still going up and down. And why `body.scrollHeight`? What if we had more than one scrollbar? – Nick Jan 30 '21 at 11:09
  • @Nick It is not something you can avoid.This is the default behaviour of a scrollbar. Depending on what you want to achieve, you could choose to display the last element at the top with the `array.unshift()` method. If you are adding a block of few lines just sometime, like in a chat, think about a smoothscrolling. Also, if you don't need to scroll after each element, you could do the scroll on the `onKeyUp` event (Or something similar). – Quentin Grisel Jan 30 '21 at 11:16
  • I see, thank you! Have you checked Messenger? They've managed to achieve it somehow. It just provides better UX. I would love to remove that `flickering/blinking`, however you name it. – Nick Jan 30 '21 at 11:21
  • @Nick It only blink when you are keeping the `entry` key down and inserting multiple message in a small time. It can also be affected by your computer performance or your browser, so I'd suggest you keep developping your feature with real content and use cases. keeping the entry key down and flooding the chat isn't something messenger allows :p – Quentin Grisel Jan 30 '21 at 11:28
  • Alright. I'll leave the post opened since I'd love to hear other opinions. P.S: It blinks no matter how fast I send the message. Even if I wait 10 mins and come back, it still does.. – Nick Jan 30 '21 at 11:36
  • @Nick I just see what you were talking about sorry. the flickering happens on your codeSandbox example but not on stackblitz (For me). It may be due to the fact that, as in Messenger, the scrollbar isn't 100% height of the body, or at least isn't a direct part of the body. It's just an idea tho – Quentin Grisel Jan 30 '21 at 11:47
  • Yeah. It's an interesting topic to dwell on. I hope someone knows. Thank you! :) – Nick Jan 30 '21 at 11:52
  • 1
    @Nick I edited my answer to provide a codepen which seems to fit your need perfectly – Quentin Grisel Jan 30 '21 at 13:18