如何在useEffect()
挂钩中添加事件监听器?
我正在使用useRef()
定位nav元素,然后选择所有链接后代。然后,我尝试向这些链接元素添加事件侦听器,但出现错误。
这是我的组件代码的一部分:
let navRef = useRef();
useEffect(() => {
let links = sideDrawerRef.current.querySelectorAll('ul li a');
links.addEventListener('click', () => {
console.log('hay');
});
});
<nav ref={navRef} >
<ul>
<li><a href="#">Link A</a></li>
<li><a href="#">Link B</a></li>
</ul>
</nav>
我遇到以下错误:
links.addEventListener不是函数
答案 0 :(得分:3)
与其添加事件处理程序,不如考虑通过onClick
道具将事件绑定委托给React。
这样做可以简化组件的实现:
let navRef = useRef();
const onClickLink = () => {
console.log('hay');
}
<nav ref={navRef} >
<ul>
<li><a href="#" onClick={onClickLink}>Link A</a></li>
<li><a href="#" onClick={onClickLink}>Link B</a></li>
</ul>
</nav>
还要在当前代码上添加一些注释,以解释一些问题;
querySelectorAll()
方法returns a NodeList
。要将点击事件处理程序添加到所有选定的节点,必须迭代每个节点并一次添加事件侦听器:
let links = someAnscestor.querySelectorAll('ul li a');
for(const link of links) {
/* Add click to currently iterated link node in NodeList result */
link.addEventListener('click', () => {
console.log('hay');
});
}
此外,此处使用useEffect()
的方式将导致每次渲染组件时都运行效果。 Adding []
as the second argument to useEffect()
将使效果回调在启动时运行一次,这将更适合此处:
useEffect(() => {
console.log("I only run when the component first mounts");
return () => {
console.log("I run when the component is unmounted");
}
}, []); // <-- [] causes effect to run once