I wanted to make the modal popup if someone leaves the window.
I tried the following code:
React.useEffect(() => {
const popupWhenLeave = (event) => {
if (
event.clientY <= 0 ||
event.clientX <= 0 ||
event.clientX >= window.innerWidth ||
event.clientY >= window.innerHeight
) {
handleClickOpen();
}
};
document.addEventListener("mouseleave", popupWhenLeave);
return () => {
document.removeEventListener("mouseleave", popupWhenLeave);
};
}, []);
The above code helped me but became annoying as it pops up every interval. I tried adding a new state to run the code only once:
const [cursorOut, setCursorOut] = useState(false);
React.useEffect(() => {
const popupWhenLeave = (event) => {
if (
event.clientY <= 0 ||
event.clientX <= 0 ||
event.clientX >= window.innerWidth ||
event.clientY >= window.innerHeight
) {
handleClickOpen();
}
};
if(!cursorOut) {
document.addEventListener("mouseleave", popupWhenLeave);
setCursorOut(true);
}
return () => {
document.removeEventListener("mouseleave", popupWhenLeave);
};
}, []);
The above code also ran the same as the previous one i.e. every time the modal would pop up.
I tried to add the dependency to useEffect [cursorOut]
but now it won't pop the modal.
I need to pop up the modal only once on the page when the cursor is out and then stop.
P.S. I also tried without useEffect and it doesn't work.
CodePudding user response:
Your useEffect
function is only called once, when the dependency array is empty. However, your useEffect
function adds an event listener to the page, which fill be called every time the event occurs.
If you want to only listen to the event once, you should remove the event listener in the popupWhenLeave
function and not only in the useEffect
clean up function you return at the end.
React.useEffect(() => {
const popupWhenLeave = (event) => {
if (
event.clientY <= 0 ||
event.clientX <= 0 ||
event.clientX >= window.innerWidth ||
event.clientY >= window.innerHeight
) {
handleClickOpen();
document.removeEventListener("mouseleave", popupWhenLeave);
}
};
document.addEventListener("mouseleave", popupWhenLeave);
return () => {
document.removeEventListener("mouseleave", popupWhenLeave);
};
}, []);
Sidenote: If your component is recreated because e.g. a parent component changed, the useEffect
function will be called again regardless of the contents of the dependency array.