useBeforeUnload
A React hook that listens for the `beforeunload` event.
Example
import { useState } from "react";
import useBeforeUnload from "@/hooks/useBeforeUnload";
export default function UseBeforeUnloadExample() {
  const [isEnabled, setIsEnabled] = useState(true);
  useBeforeUnload(isEnabled, "Hello from beforeunload");
  return (
    <div className="flex flex-col items-center justify-center gap-4 p-4">
      <p className="text-ctp-text">{isEnabled ? "Enabled" : "Disabled"}</p>
      <a href="https://example.com" className="text-ctp-blue underline">
        Quit this page
      </a>
      <div className="flex flex-row items-center justify-center gap-4 p-4">
        <button
          className="rounded bg-ctp-green px-4 py-2 text-ctp-base"
          onClick={() => setIsEnabled(true)}
        >
          Enable
        </button>
        <button
          className="rounded bg-ctp-red px-4 py-2 text-ctp-base"
          onClick={() => setIsEnabled(false)}
        >
          Disable
        </button>
      </div>
    </div>
  );
}  Code
import { useCallback, useEffect } from "react";
/**
 * A React hook that listens for the `beforeunload` event.
 *
 * @param {boolean} enabled - A boolean or a function that returns a boolean. If the
 * function returns `false`, the event will be prevented.
 * @param {string | undefined} message - An optional message to display in the dialog.
 */
export default function (
  enabled: boolean | (() => boolean) = true,
  message?: string,
) {
  const handler = useCallback(
    (event: BeforeUnloadEvent) => {
      const finalEnabled = typeof enabled === "function" ? enabled() : true;
      if (!finalEnabled) {
        return;
      }
      event.preventDefault();
      if (message) {
        event.returnValue = message;
      }
      return message;
    },
    [enabled, message],
  );
  useEffect(() => {
    if (!enabled) {
      return;
    }
    window.addEventListener("beforeunload", handler);
    return () => window.removeEventListener("beforeunload", handler);
  }, [enabled, handler]);
}