React Typescript:使用 Ref 侦听外部触摸事件不起作用



我有一个组件(navBar),它有两个实例:Default和Responsive。它在屏幕上的形状是由样式(sass)定义的,由handleClick函数。

我决定在body元素上放置一个侦听器,如果在Menu之外有点击,该函数将手动从Menu classList中取出'active' className。

function useOutsideListener(ref: React.MutableRefObject<null | HTMLDivElement>) {
useEffect(() => {
function handleClickOutside(event: MouseEvent | TouchEvent) {
if (ref.current && !ref.current.contains(event.target as Element)) {
activeMenu.forEach((itens) => {
itens.classList.remove(styles['active']);
});
};
};
document.addEventListener("touchstart", handleClickOutside);
return () => {
document.removeEventListener("touchstart", handleClickOutside);
};
}, [ref]);
}

包装器被正确地附加到ref属性上,逻辑工作正常,但只有在vsCode中保存文件并"重新渲染"组件之后。我知道这和useRef有关,但是我不知道如何解决这个问题。

function renderNavBar() {
const wrapperRef = useRef<HTMLDivElement>(null);
useOutsideListener(wrapperRef);
return (
<div className={styles.navBar} ref={wrapperRef}>
<button className={styles.menu} onClick={ handleClick } data-menu>MENU</button>
<nav className={styles.navContainer} data-menu>
<ul className={styles.navList}>
<Link to="/exp">Experiência</Link>
<Link to="/formacao">Formação</Link>
<Link to="/projects">Projetos</Link>
<Link to="/contact">Contato</Link>
</ul>
</nav>
</div>
);
}

我可能以错误的方式使用了我不太了解的工具。我最终发现了useCallback,并更准确地监控了ref属性。最终的函数结果如下所示:

const useOutsideListener = (): [
RefObject<HTMLDivElement>,
(node: HTMLDivElement) => void
] => {
const ref = useRef<HTMLDivElement | null>(null);
const setRef = useCallback((node: HTMLDivElement) => {
ref.current = node;
}, [ref.current]);
return [ref, setRef]
}

使用useEffect,我监视了ref对象状态的变化,并且为了一个简单的检查,删除了样式类。

useEffect(() => {
if(ref.current?.attributes[1].value === 'true') {

document.body.addEventListener('touchstart', function handleOutside(event) {
setTimeout(() => {
const menuButton = (event.target as HTMLElement).parentElement;
if(menuButton !== ref.current) {
ref.current?.querySelector('nav')?.classList.remove(styles['active']);
document.body.removeEventListener('touchstart', handleOutside);
}}, 75);
});
};

}, [ref.current?.attributes[1].value]);

最新更新