-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support a before-unload prompt on forms (#151)
* Add latest react router * Add useprompt feature * Fix Merge duplicates --------- Co-authored-by: John Cherry <github@johncherry.me>
- Loading branch information
1 parent
3750d5d
commit 22552d4
Showing
4 changed files
with
54 additions
and
0 deletions.
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import * as React from 'react' | ||
import { useBeforeUnload, unstable_useBlocker as useBlocker } from 'react-router-dom' | ||
|
||
// From https://gist.github.com/chaance/2f3c14ec2351a175024f62fd6ba64aa6 | ||
|
||
// You can abstract `useBlocker` to use the browser's `window.confirm` dialog to | ||
// determine whether or not the user should navigate within the current origin. | ||
// `useBlocker` can also be used in conjunction with `useBeforeUnload` to | ||
// prevent navigation away from the current origin. | ||
// | ||
// IMPORTANT: There are edge cases with this behavior in which React Router | ||
// cannot reliably access the correct location in the history stack. In such | ||
// cases the user may attempt to stay on the page but the app navigates anyway, | ||
// or the app may stay on the correct page but the browser's history stack gets | ||
// out of whack. You should test your own implementation thoroughly to make sure | ||
// the trade offs are right for your users. | ||
|
||
export const usePrompt = ( | ||
message: string | null | undefined | false, | ||
{ beforeUnload }: { beforeUnload?: boolean } = {} | ||
) => { | ||
const blocker = useBlocker( | ||
React.useCallback(() => (typeof message === 'string' ? !window.confirm(message) : false), [message]) | ||
) | ||
const prevState = React.useRef(blocker.state) | ||
React.useEffect(() => { | ||
if (blocker.state === 'blocked') { | ||
blocker.reset() | ||
} | ||
prevState.current = blocker.state | ||
}, [blocker]) | ||
|
||
useBeforeUnload( | ||
React.useCallback( | ||
event => { | ||
if (beforeUnload && typeof message === 'string') { | ||
event.preventDefault() | ||
event.returnValue = message | ||
} | ||
}, | ||
[message, beforeUnload] | ||
), | ||
{ capture: true } | ||
) | ||
} |