组件安装后,使用useEffect滚动到props.location.hash

时间:2019-09-23 19:12:19

标签: reactjs react-hooks

我正在创建一个词汇表页面,其中每个术语都有其自己的卡,默认情况下不会展开。每张卡都使用术语作为其ID,因为它们都是唯一的。我想支持通过URL哈希直接链接到特定术语。

因此,如果URL是localhost:3000 /#/ glossary#Actor,则初始加载将滚动到该术语并通过模拟元素的单击来“打开”卡(该元素上的单击处理程序将打开卡)

它正在工作,但是太频繁了。每当我在搜索栏中输入文本或以任何方式引起渲染时,它都会重新滚动并再次打开卡片动画。我只想首先滚动到该术语(如果存在哈希值),然后忽略它,除非它发生变化。

仅当我不包含dep数组时才有效。如果我在props.location.hash中包含一个dep数组,则el返回为null,并且什么也没有发生。我知道,由于没有dep数组,因此正在重新启动效果,但是我不知道为什么在添加它时它不起作用。

useEffect(() => {
    //looks for hash in URL; gets element associated with the hash
    let el = document.getElementById(decodeURI(props.location.hash.slice(1)));
    console.log(el)

    //if element exists, get coords and offset for header before scrolling
    if (el) {
      const yCoordinate = el.getBoundingClientRect().top + window.pageYOffset;
      const yOffset = -80; 

      window.scrollTo({
          top: yCoordinate + yOffset,
          behavior: 'smooth'
      });

      //opens the card only if not already open
      if (!el.classList.contains('openTermCard')) {
        el.click();
      }
    }
  })

useEffect可能不是正确的方法。我什至不需要钩子,idk。我只希望此初始滚动事件在页面加载时发生,而不是再次发生。

1 个答案:

答案 0 :(得分:0)

在没有可用的沙箱的情况下很难找到解决方案。

根据您的描述,在我看来,您的组件在第一次加载时渲染了多次。如果将[]设置为依赖项数组,则在尚未定义元素时,效果仅运行一次(因此,得到null的原因),这就是为什么它不起作用的原因。

一种解决方法是考虑在设计应用程序方面还可以做些什么。您提到每次组件更新时,卡都会再次聚焦,但这就是您使用useEffect时的期望。是否可以重新构造组件,以便父级(具有这种副作用的组件)不经常重新渲染?

如果您可以提供代码沙箱,我相信我(可能还有其他人)将能够为您提供进一步的帮助。