使用 componentDidUpdate 自动滚动到锚标记元素

Posted

技术标签:

【中文标题】使用 componentDidUpdate 自动滚动到锚标记元素【英文标题】:Auto scroll to anchor tag element in react using componentDidUpdate 【发布时间】:2021-01-21 06:13:18 【问题描述】: 我的网址

https://abc1234.com/users#api-doc

html

    <div className=parent>
        <div className=child>
            someContent
            <a id="api-doc">Hello API</a>
        </div>
    </div>

我正在用 ReactJS 编写页面。我需要实现一种方法,以便页面自动向下滚动到哈希,即 api-doc 但不知何故它不会在页面加载时自动滚动(第一次)。

我尝试了这样的解决方法


    componentDidUpdate()
        let id = this.props.history.location.hash.replace("#", "");
        let element = document.getElementById(id);
        setTimeout(() => 
            if (element) 
                element.scrollIntoViewIfNeeded(true);
            
        , 200);
    

它正在工作,但我正在寻找一种更好的方法来实现同样的效果

换句话说,我不想使用 setTimeOut。

我添加了 setTimeOut,因为我发现 document.getElementById(id) 给出了 null(第一次),我假设 componentDidUpdate 在整个渲染之前以某种方式运行。我还使用了 dangerouslySetInnerHTML 。

【问题讨论】:

【参考方案1】:

document.getElementById(id) 返回 null 是正确的,因为该元素尚未渲染。

在 React 中不要使用 document.getElementById()。 React 节点本身并不是真正的 DOM 节点(例如,文本或元素节点),而是潜在 DOM 节点的表示。

改为使用钩子useRef()React documentation

创建以下组件。

import React,  useRef, useEffect   from 'react';

const myComponent = (props) => 

  const myRef = useRef();

  function scrollToComponent() 
    if (window.location.hash === '#api-doc') 
      myRef.current.scrollIntoView();
      myRef.current.focus();
    
  

  useEffect( () => scrollToComponent(), [] )

  return (
    <div ref=myRef id="api-doc">
       ...
    </div>
  )
;

export default myComponent;

以这种方式使用useEffect 将(仅)在组件挂载时触发。 (因此避免了JS在组件挂载之前运行的问题)

我命名为 scrollToComponent 的函数将检查 URL 的哈希值,如果它通过条件,它将滚动到引用。

记得将组件导入到你的主文件中。

*注意:使用 React 路由器的 Link 可能是更好的解决方案。 (但我不熟悉)

【讨论】:

以上是关于使用 componentDidUpdate 自动滚动到锚标记元素的主要内容,如果未能解决你的问题,请参考以下文章

笔记本电脑如何实现自动滚屏

与 setState 回调相比,使用 componentDidUpdate 有啥优势?

使用 componentDidUpdate 在反应中更新状态

componentDidUpdate 中的 prevState 是 currentState?

componentDidUpdate 没有触发

如何处理 ComponentDidUpdate 中的异步数据?