javascript - 反应如何等待组件/页面呈现调用函数
问题描述
我需要修改这里返回的第一个 div 的 data-scroll 属性。问题似乎是种族危险 - 因为 dom 尚未加载,所以 active 为 null。我该如何处理?异步/等待?我没有查询任何内容,也不会得到回复。我如何等到 Header 被渲染?
这会生成 TypeError:无法读取 null 的属性“数据集”:
import { Link } from 'react-router-dom';
import * as ROUTES from '../constants/routes';
export default function Header() {
const active = document.getElementById('navbar');
const debounce = (fn) => {
let frame;
return (...params) => {
if (frame) {
cancelAnimationFrame(frame);
}
frame = requestAnimationFrame(() => {
fn(...params);
});
};
};
const storeScroll = () => {
if (window.scrollY > 80) {
active.dataset.scroll = window.scrollY;
}
if (window.scrollY <= 80) {
active.dataset.scroll = 0;
}
};
// Listen for new scroll events
document.addEventListener('scroll', debounce(storeScroll), { passive: true });
// Update scroll position for first time
storeScroll();
return (
<div id="navbar" data-scroll="0">
<header className="fixed flex top-0 scroll:bg-blue-500 bg-transparent items-center justify-center p-5 w-full">
<div className="container mx-auto max-w-screen-lg h-full">
<div className="flex justify-between h-full">
<div className="text-black text-center flex items-center align-items cursor-pointer">
<h1 className="flex justify-center w-full">
<Link to={ROUTES.TEST} className="font-bold text-lg" aria-label="home">
HOME
</Link>
</h1>
</div>
</div>
</div>
</header>
</div>
);
}
解决方案
在 react 中直接定位底层 DOM 并不是一个好习惯。我们可以使用ref
来做到这一点。
此外,当组件卸载时,您正在添加一个eventListener
未正确删除的组件。所以为了确保在渲染完成时你有元素,你可以使用useEffect
钩子来保证它在绘制 DOM 之后运行。
所以你需要让你的 eventListener 代码在 useEffect hook 中移动。Ref
这是使用和的更新代码useEffect
。
import {Link} from 'react-router-dom';
import * as ROUTES from '../constants/routes';
import {useRef, useEffect} from 'react';
export default function Header() {
const navbarRef = useRef();
const debounce = (fn) => {
let frame;
return (...params) => {
if (frame) {
cancelAnimationFrame(frame);
}
frame = requestAnimationFrame(() => {
fn(...params);
});
};
};
const storeScroll = () => {
if (window.scrollY > 80) {
navbarRef.current.dataset.scroll = window.scrollY;
}
if (window.scrollY <= 80) {
navbarRef.current.dataset.scroll = 0;
}
};
useEffect(() => {
// Update scroll position for first time
storeScroll();
// attact the event listener
window.addEventListener('scroll', debounce(storeScroll), {passive: true});
// remove the event listener when the component is unmounted
return () =>
window.removeEventListener('scroll', debounce(storeScroll), {
passive: true,
});
}, []);
return (
<div id="navbar" ref={navbarRef} data-scroll="0">
<header className="fixed flex top-0 scroll:bg-blue-500 bg-transparent items-center justify-center p-5 w-full">
<div className="container mx-auto max-w-screen-lg h-full">
<div className="flex justify-between h-full">
<div className="text-black text-center flex items-center align-items cursor-pointer">
<h1 className="flex justify-center w-full">
<Link
to={ROUTES.TEST}
className="font-bold text-lg"
aria-label="home"
>
HOME
</Link>
</h1>
</div>
</div>
</div>
</header>
</div>
);
}
推荐阅读
- python - 将一个类中的信息保存到另一个模块中并让它们相互影响
- javascript - TypeError:parentSubmit 不是函数
- oracle - 在本地开发中设置本地 Oracle 数据库的最快方法
- flutter - 将 Flutter Intl 与常量一起使用,而无需引用上下文
- twitter - 如何将 Twitter api 与 mule 集成
- .net-core - 运行独立后台进程的正确方法
- c# - 'Amazon.Runtime.Internal.FallbackInternalConfigurationFactory' 引发异常
- java - windowClosing() 方法没有被调用
- java - 当它在后端触发作业时,如何立即从rest api发送响应?
- node.js - 通过在 moment() 中从查询参数传递字符串显示 moment.invalid