首页 > 解决方案 > 没有超时功能,无法在 useEffect 中设置 HTMLElement 的 scrollTop

问题描述

我有一个文本日志组件,只要它收到新的日志条目,我就想滚动到底部,所以我将它的父级scrollTop设置scrollHeightuseEffect(). 但是,这没有效果:

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>

    )
}

另一方面,此代码有效:

...
useEffect(() => {
    if (logRef && logRef.current) {
        let parent = logRef.current.parentNode as HTMLDivElement
        setTimeout(() => {
            parent.scrollTop = parent.scrollHeight;
        }, 100)
    }     
})
...

在我的机器上,我可以将超时设置为低至 39,并且它会始终如一地工作。较低的数字有零星的成功。大概这个数字会因某些性能指标而异,但我不知道。

控制台日志显示 ref 存在,并且它确实有足够的高度来滚动时间useEffect()触发器。之前和之后的记录parent.scrollTop = parent.scrollHeight;表明这scrollTop不会改变。

我是否误解了useEffect()它的工作原理,是因为我正在设置父母的scrollTop,还是我还缺少其他东西?

标签: reactjstypescriptreact-hooksuse-effect

解决方案


您可以通过进行一些更改来实现它:

useEffect(() => {
  logRef.current.scrollIntoView({ behavior: 'smooth', block: 'end' })
}, [entries])

您可以在Mozilla DocsscrollIntoView中查看支持功能的浏览器列表。如果你想要更多的浏览器支持,那么你可以安装这个名为smoothscroll-polyfill 的小型 npm 包。


推荐阅读