我有一个自定义钩子,用于处理组件外部的点击:
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回调函数。我该如何解决这个问题?
答案 0 :(得分:1)
这里的问题是Finished
没有依赖项数组,因此在每个渲染器上都将调用它。另外,最好将useEffect
的定义保留在钩子中,因为它将仅在第一个渲染中使用。否则,将在每个渲染器上进行定义。
handleClick
答案 1 :(得分:0)
我发现useOutsideClick挂钩的最佳解决方案是:
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]
);
}