【问题标题】:React useEffect strange behaviour with custom layout component使用自定义布局组件反应 useEffect 奇怪的行为
【发布时间】:2021-03-03 09:30:28
【问题描述】:

我正在尝试在我的网络作品集中为我的动画使用滚动位置。由于这个投资组合使用 nextJS,我不能依赖 window 对象,而且我使用的是导航宽滑块,所以我实际上不是在窗口中滚动,而是在一个名为 Page 的布局组件中滚动。

import React, { useEffect } from 'react';
import './page.css';

const Page = ({ children }) => {

  useEffect(() => {
    const scrollX = document.getElementsByClassName('page')
    const scrollElement = scrollX[0];
    console.log(scrollX.length)
    console.log(scrollX)
    scrollElement.addEventListener("scroll", function () {
      console.log(scrollX[0].scrollTop)
    });
 
    return () => {
      scrollElement.removeEventListener("scroll", () => { console.log('listener removed') })
    }
  }, [])


  return <div className="page">{children}</div>;
};

export default Page;

这是一个生产版本:https://next-portfolio-kwn0390ih.vercel.app/

加载时,DOM 中只有一个 Page 组件。

行为如下:

  • 在第一次挂载页面时添加第一个监听器,在导航时,还会在 DOM 中添加监听器以及新的页面组件。
  • 只要您在两个页面之间导航,就不会添加新的侦听器/页面
  • 如果导航到第三个页面,则在卸载旧页面时删除监听器,并在装载第三个页面时添加第三个页面的新监听器(等等...)

问题是:当您从第一个导航到第二个时,一切看起来都很好,但是如果您返回第一页,您会注意到控制台正在记录第二个侦听器的 scrollX 值,而不是第一个侦听器。每次进入第二页时,它似乎都会向同一个 scrollElement 添加另一个侦听器,即使它不是同一个 Page 组件。

我该怎么做?我猜这两个组件正在尝试访问相同的 scrollElement :/

感谢您的宝贵时间。

【问题讨论】:

    标签: reactjs react-hooks next.js use-effect


    【解决方案1】:

    很酷的网站。我们没有完整的信息,但我怀疑尝试使用 document.getElementsByClassName('page')[0] 时存在问题。当您转到第 2 页时,scrollX 的日志会给出一个包含 2 个元素的 HTMLCollection。所以有一个问题是针对哪个。我会考虑使用 refs 代替。像这样:

    import React, { useEffect, useRef } from 'react';
    import './page.css';
    
    const Page = ({ children }) => {
    
      const pageRef = useRef(null)
    
      const scrollListener = () => {
        console.log(pageRef.current.scrollTop)
      }
    
      useEffect(() => {
        pageRef.addEventListener("scroll", scrollListener );
     
        return () => {
          pageRef.removeEventListener("scroll", scrollListener )
        }
      }, [])
    
    
      return <div ref={pageRef}>{children}</div>;
    };
    
    export default Page;
    

    这更加简洁,我认为这将减少组件之间关于每个滚动侦听器引用的 dom 元素的混淆。就第三页而言,您的 scrollX 仍在记录相同的 HTMLElement 集合,其中包含 2 个元素。根据您的模式,应该有 3 个。(尽管实际上应该只有 1 个!)所以第 3 页上的某些内容没有正确呈现。 如果我们看到更多代码,它可能会发现错误是别的东西。如果 refs 没有解决它,你能发布 Page 在更大范围内是如何实现的吗?

    另外,从“初级开发者”标题中删除“初级”——你不会后悔的

    【讨论】:

    • 嘿,感谢您的网站 :p 您的解决方案就像一个魅力。只需在您提供的 useEffect 中将 pageRef 更改为 pageRef.current 即可。感谢您对 useRef 挂钩的见解;)
    猜你喜欢
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 2014-08-06
    • 1970-01-01
    • 2014-02-25
    • 2014-10-06
    相关资源
    最近更新 更多