johnbbab
johnbbab

Reputation: 133

eventlistener beforeunload not working in react

I am trying to open a popup while a user closes a tab in react using this code:

useEffect(() => {
    
    window.addEventListener('beforeunload',handleUnload );
    return () => {
      window.removeEventListener('beforeunload', handleUnload);
    }
  }, []);
  

  const handleUnload = (e) => {
    e.preventDefault();
   console.log('hey')
   alert("HEY");
  }

is there any other way to do this or is there any way I can correct the code. Currently I'm trying to alert the user.

Upvotes: 5

Views: 18065

Answers (3)

Scott Weaver
Scott Weaver

Reputation: 51

I know this isn't an exact answer to what OP was asking, but I came across this while trying to figure out how to prompt only when the user has unsaved changes. I finally got that logic working with the following code:

<pre>
    let [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false);

    const [unsavedChangesCallback, setUnsavedChangesCallback] = React.useState(() => (e) => {
        let message = "You have unsaved changes, are you sure you want to leave?";
        e.returnValue = message;
        return message;
    });

    useEffect(() => {
        if (hasUnsavedChanges) {
            window.addEventListener('beforeunload', unsavedChangesCallback);
        } else {
            window.removeEventListener('beforeunload', unsavedChangesCallback);
        }
    }, [hasUnsavedChanges, unsavedChangesCallback]);
</pre>

Then all you have to do is update the value of hasUnsavedChanges whether or not your application currently has unsaved changes, and it will prompt accordingly.

Upvotes: 0

Artur Grigio
Artur Grigio

Reputation: 5553

Try using a ref:

const useUnload = (fn) => {
  const cb = React.useRef(fn);

  React.useEffect(() => {
    const onUnload = cb.current;
    window.addEventListener('beforeunload', onUnload);
    return () => {
      window.removeEventListener('beforeunload', onUnload);
    };
  }, [cb]);
};

And then use this to call

useUnload((e) => {
  e.preventDefault();
  console.log('hey')
  alert("HEY");
});

Upvotes: 2

milano_jon
milano_jon

Reputation: 76

welcome to SO!

I think you have unintentionally destructured your function using the {}.

try this:

useEffect(() => {
  window.addEventListener("beforeunload", handleUnload);

  return () => window.removeEventListener("beforeunload", handleUnload);
}, [handleUnload]);

I've added [handleUnload] to the 2nd attribute of useEffect to prevent it adding and removing the event listener upon every state change.

Upvotes: 0

Related Questions