I have a text log component that I want to scroll to the bottom whenever it receives a new log entry, so I have it set the parent's scrollTop
to it's scrollHeight
in useEffect()
. However, this has no effect:
const Log = ({ entries }: LogProps) => {
const logRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (logRef && logRef.current) {
let parent = logRef.current.parentNode as HTMLDivElement
parent.scrollTop = parent.scrollHeight;
}
})
return (
<Module className="log" title="Text Log">
<div ref={logRef} className="log__entries">
...
</div>
</Module>
)
}
This code on the other hand, works:
...
useEffect(() => {
if (logRef && logRef.current) {
let parent = logRef.current.parentNode as HTMLDivElement
setTimeout(() => {
parent.scrollTop = parent.scrollHeight;
}, 100)
}
})
...
On my machine, I can set the timeout as low as 39, and it'll work consistently. Lower numbers have sporadic success. Presumably that number will vary by some performance metric, but I have no idea.
Console logging shows that the ref exists, and it does have height enough to scroll by the time useEffect()
triggers. Logging before and after parent.scrollTop = parent.scrollHeight;
reveals that scrollTop
doesn't change.
Am I misunderstanding how useEffect()
works, is it because I'm setting the parent's scrollTop
, or is there something else I'm missing?