javascript - 当组件在反应中卸载时消除功能的副作用?
问题描述
我正在开发一个 react-app 并使用以下功能来跟踪我的导航面板中的活动链接。
以下函数用于IntersectionObserver
跟踪给定元素是否在视口中。
该代码能够解决其动机。
但是当我将路由更改为不同的组件时,它会显示错误 -TypeError: Cannot read property 'parentElement' of null
那是因为使用该功能的组件changeActiveLink();
不再在页面中(它已被卸载)。
我想在移除组件时移除此功能的效果。
我尝试将它与该事件侦听器集成DOMContentLoaded eventListener
,然后清理该事件侦听器,但该事件侦听器仅适用于 HTML 文档的第一次渲染,并且当我们在所需路由上渲染组件而使函数changeActiveLink();
未初始化时不起作用。
我应该如何让这个功能只在这个特定的组件中工作,并避免它对其他组件的影响?
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();
}, []);
解决方案
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
}, []);
推荐阅读
- android - 微调器未从 Firebase 填充
- python - 如何只保留 Pandas 数据框中线/列交叉点周围的数据?
- node.js - NodeJS - 与尝试 ntlm 身份验证的服务器通信,但遇到奇怪的行为
- python - pytest --capture=fd :文件在哪里创建?
- amazon-sns - 在 Grafana 中显示 Cloudwatch 警报
- python - scatter 函数如何在 python 中工作以绘制图形
- raku - Perl6:第一个数组元素放入字符串,第二个未能放入字符串
- c++ - Visual Studio 和 Xcode 之间的 Chaiscript 字符串问题
- java - Jenkins Groovy:将参数转换为大写
- ruby-on-rails - Rails 5:没有控制器的嵌套路由