【问题标题】:remove the side-effect of function when the component is unmounted in react?当组件在反应中卸载时消除功能的副作用?
【发布时间】:2021-06-27 09:52:22
【问题描述】:

我正在开发一个 react-app 并使用以下功能来跟踪我的导航面板中的活动链接。

以下函数使用IntersectionObserver 来跟踪给定元素是否在视口中。

代码能够解决其动机。
但是当我将路由更改为不同的组件时,它会显示错误 - TypeError: Cannot read property 'parentElement' of null

那是因为使用函数changeActiveLink();的组件不在页面中(它被卸载了)。

我想在移除组件时移除这个函数的效果。

我尝试将它与 DOMContentLoaded eventListener 集成,然后清理该事件侦听器,但此事件侦听器仅适用于 HTML 文档的第一次渲染,并且当我们在所需路由上渲染组件时不起作用,而函数 changeActiveLink(); 未初始化。

我应该如何让这个功能只在这个特定的组件中起作用,并避免它对其他组件的影响?

Screenshot of error screen

useEffect(() => {
    const changeActiveLink = () => {
      
      const scrollHandler = (entries) => {
        entries.forEach((entry) => {
          const id = entry.target.getAttribute("id");

          if (entry.intersectionRatio > 0) {
            document
              .querySelector(`nav li a[href="#${id}"]`)
              .parentElement.classList.add("active");
          } else {
            document
              .querySelector(`nav li a[href="#${id}"]`)
              .parentElement.classList.remove("active");
          }
        });
      };

      const observer = new IntersectionObserver(scrollHandler);

      // Track all sections that have an `id` applied
      document.querySelectorAll("section[id]").forEach((section) => {
        observer.observe(section);
      });
    };

    changeActiveLink();
    
  }, []);

【问题讨论】:

    标签: javascript html reactjs react-router react-hooks


    【解决方案1】:

    返回一个useEffect cleanup functionun-observe 目标元素:

    useEffect(() => {
      const changeActiveLink = () => {
    
        const scrollHandler = (entries) => {
          entries.forEach((entry) => {
            const id = entry.target.getAttribute("id");
    
            if (entry.intersectionRatio > 0) {
              document
                .querySelector(`nav li a[href="#${id}"]`)
                .parentElement.classList.add("active");
            } else {
              document
                .querySelector(`nav li a[href="#${id}"]`)
                .parentElement.classList.remove("active");
            }
          });
        };
    
        const observer = new IntersectionObserver(scrollHandler);
    
        const sections = document.querySelectorAll("section[id]");
    
        // Track all sections that have an `id` applied
        sections.forEach((section) => {
          observer.observe(section);
        });
        
        return () => {
          // untrack all sections that have an `id` applied
          sections.forEach((section) => {
            observer.unobserve(section);
          });
        }; // return the cleanup function
      };
    
      return changeActiveLink(); // you should also return the function here
    
    }, []);
    

    【讨论】:

    • 谢谢,这很有帮助。
    • 不客气。如果它解决了您的问题,您应该接受答案。
    猜你喜欢
    • 2021-03-13
    • 2019-10-02
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 1970-01-01
    • 2018-03-25
    • 2022-10-15
    相关资源
    最近更新 更多