reactjs - 使用自定义布局组件反应 useEffect 奇怪的行为
问题描述
我正在尝试在我的网络投资组合中为我的动画使用滚动位置。由于这个投资组合使用 nextJS,我不能依赖窗口对象,而且我使用的是导航宽滑块,所以我实际上不是在窗口中滚动,而是在一个名为 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 值。每次您进入第二页时,即使它不是同一个 Page 组件,它似乎也会向同一个 scrollElement 添加另一个侦听器。
我怎样才能做到这一点 ?我猜这两个组件正在尝试访问相同的 scrollElement :/
谢谢你的时间。
解决方案
很酷的网站。我们没有完整的信息,但我怀疑尝试使用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
在更大范围内是如何实现的吗?
另外,从“初级开发人员”标题中删除“初级” - 你不会后悔的
推荐阅读
- python - 将 12 通道小图像的值分配给 3 通道大图像张量流
- python - 如何在 python 中动态获取组的组合/排列?
- vue.js - 如何在 VueJS 中使用过滤/转换的数据创建可点击的锚标记
- spring - Java Spring Eclipse Tomcat - RestTemplate,使用 HTTPS API
- c# - C# 8 是否注释了可为空的属性和参数?
- oracle - 使用游标将表数据提取到表中
- javascript - 基于时区 24 小时后的循环计数器
- java - 井字游戏客户端服务器交互
- javascript - 使用 WhatsApp HTML 链接分享图片和网址
- java - 你如何遍历scala中的每个状态?