Created
April 11, 2023 10:25
-
-
Save julenwang/e3754863c695679a6bea7d454187a628 to your computer and use it in GitHub Desktop.
useAsyncBlocker for react-router v6.7+
This file contains hidden or 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 { useCallback, useRef } from 'react'; | |
import { unstable_useBlocker as useBlocker, useBeforeUnload, useNavigate } from 'react-router-dom'; | |
function useAsyncBlocker(isBlockFn: () => Promise<boolean>) { | |
const navigate = useNavigate(); | |
const isBlockRef = useRef(true); | |
const blockerArgsRef = useRef<Parameters<Exclude<Parameters<typeof useBlocker>[0], boolean>>[0]>(); | |
const willBlock = useCallback(async () => { | |
const isBlock = await isBlockFn(); | |
isBlockRef.current = isBlock; | |
if (!isBlock) { | |
const { nextLocation, historyAction } = blockerArgsRef.current!; | |
if (historyAction === 'POP') { | |
navigate(-1); | |
} else { | |
navigate(nextLocation, { replace: historyAction === 'REPLACE' }); | |
} | |
} | |
}, [isBlockFn, navigate]); | |
useBlocker((args) => { | |
blockerArgsRef.current = args; | |
willBlock(); | |
return isBlockRef.current; | |
}); | |
useBeforeUnload((event) => { | |
if (isBlockRef.current) { | |
event.preventDefault(); | |
event.returnValue = ''; | |
} | |
}); | |
} | |
export default useAsyncBlocker; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment