更新状态时,带有事件侦听器的React自定义挂钩不起作用



我有一个自定义挂钩,可以处理组件外部的点击:

const useOutsideClick = (ref, callback) => {
const handleClick = e => {
if (ref.current && !ref.current.contains(e.target)) {
callback();
}
};
useEffect(() => {
document.addEventListener("click", handleClick);
return () => {
document.removeEventListener("click", handleClick);
};
});
};

我在这样的组件中使用了这个钩子:

const MyComponent = () => {
const container = useRef();
const [isOpen, setIsOpen] = useState(false);
useOutsideClick(container, () => {
console.log("clicked outside");
});
return (
<>
<span>another element</span>
<button onClick={() => setIsOpen(false)}>click</button>
<div ref={container}></div>
</>
);
};

问题是,当我点击跨度时,一切都很好。但是,当我点击按钮时,它会更新状态,它不会进入useOutsideClick回调函数。我该如何解决这个问题?

这里的问题是useEffect没有依赖数组,因此在每次渲染时都会调用它。此外,最好将handleClick的定义保留在钩子内,因为它只会在第一次渲染中使用;否则将在每个渲染上定义if。

const useOutsideClick = (ref, callback) => {
useEffect(() => {
const handleClick = e => {
if (ref.current && !ref.current.contains(e.target)) {
callback();
}
};
document.addEventListener("click", handleClick);
return () => {
document.removeEventListener("click", handleClick);
};
}, []);
};

我发现使用OutsideClick钩子的最佳解决方案是:

function useOutsideClick(ref, handler) {
useEffect(
() => {
const listener = event => {
if (!ref.current || ref.current.contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener("mousedown", listener);
document.addEventListener("touchstart", listener);
return () => {
document.removeEventListener("mousedown", listener);
document.removeEventListener("touchstart", listener);
};
},
[ref, handler]
);
}

相关内容

  • 没有找到相关文章

最新更新