Created
May 4, 2020 13:47
-
-
Save brendancarney/28fef2a00c79c6c387af93c744f70f36 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect } from "react" | |
import { confirm } from "../modals" | |
const hrefBlank = element => { | |
const href = element.getAttribute("href") | |
return !href || href === "#" | |
} | |
function useBeforeLeave({ | |
message = "", | |
title = "Unsaved Changes", | |
enabled = true, | |
confirm: confirmText = "Leave without saving", | |
cancel = "Cancel", | |
} = {}) { | |
useEffect(() => { | |
const handleClick = async event => { | |
if (!enabled) return | |
const element = event.target | |
if (element.matches("a") && !element.dataset.confirmed) { | |
// don't trigger for empty href | |
if (hrefBlank(element)) return | |
// don't trigger if the link would open in a new window | |
if (element.target === "_blank") return | |
if (element.isContentEditable) return | |
// We always prevent the default action because the event listener is | |
// synchronous, and determining if the user wants to navigate away is | |
// asynchronous. | |
event.preventDefault() | |
const confirmation = await confirm(title, { | |
message, | |
confirm: confirmText, | |
cancel, | |
}) | |
if (confirmation) { | |
// Once confirmed, set data-confirm so we can retrigger the click, | |
// but not prompt for confirmation next time. | |
element.dataset.confirmed = true | |
element.click() | |
} | |
} | |
} | |
document.addEventListener("click", handleClick) | |
return () => document.removeEventListener("click", handleClick) | |
}, [message, title, enabled, confirmText, cancel]) | |
} | |
export default useBeforeLeave |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment