From 4f1ef580c26d119667f5116484240ae9cefb84ca Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Thu, 2 Feb 2023 10:15:07 -0500 Subject: [PATCH] Remove inaccurate console warning for POP navigations --- .changeset/healthy-moons-compete.md | 6 +++++ packages/react-router/lib/hooks.tsx | 10 ++++---- packages/router/router.ts | 36 ++++++++++------------------- 3 files changed, 24 insertions(+), 28 deletions(-) create mode 100644 .changeset/healthy-moons-compete.md diff --git a/.changeset/healthy-moons-compete.md b/.changeset/healthy-moons-compete.md new file mode 100644 index 0000000000..226d71fad9 --- /dev/null +++ b/.changeset/healthy-moons-compete.md @@ -0,0 +1,6 @@ +--- +"react-router": patch +"@remix-run/router": patch +--- + +Remove inaccurate console warning for POP navigations diff --git a/packages/react-router/lib/hooks.tsx b/packages/react-router/lib/hooks.tsx index 259521a516..f766c26e83 100644 --- a/packages/react-router/lib/hooks.tsx +++ b/packages/react-router/lib/hooks.tsx @@ -831,9 +831,7 @@ export function useAsyncError(): unknown { return value?._error; } -// useBlocker() is a singleton for now since we don't have any compelling use -// cases for multi-blocker yet -let blockerKey = "blocker-singleton"; +let blockerId = 0; /** * Allow the application to block navigations within the SPA and present the @@ -843,6 +841,7 @@ let blockerKey = "blocker-singleton"; */ export function useBlocker(shouldBlock: boolean | BlockerFunction): Blocker { let { router } = useDataRouterContext(DataRouterHook.UseBlocker); + let [blockerKey] = React.useState(() => String(++blockerId)); let blockerFunction = React.useCallback( (args) => { @@ -856,7 +855,10 @@ export function useBlocker(shouldBlock: boolean | BlockerFunction): Blocker { let blocker = router.getBlocker(blockerKey, blockerFunction); // Cleanup on unmount - React.useEffect(() => () => router.deleteBlocker(blockerKey), [router]); + React.useEffect( + () => () => router.deleteBlocker(blockerKey), + [router, blockerKey] + ); return blocker; } diff --git a/packages/router/router.ts b/packages/router/router.ts index 1f56b629e1..8be581c3b4 100644 --- a/packages/router/router.ts +++ b/packages/router/router.ts @@ -754,10 +754,6 @@ export function createRouter(init: RouterInit): Router { // cancel active deferreds for eliminated routes. let activeDeferreds = new Map(); - // We ony support a single active blocker at the moment since we don't have - // any compelling use cases for multi-blocker yet - let activeBlocker: string | null = null; - // Store blocker functions in a separate Map outside of router state since // we don't need to update UI state if they change let blockerFunctions = new Map(); @@ -782,7 +778,7 @@ export function createRouter(init: RouterInit): Router { } warning( - activeBlocker != null && delta === null, + blockerFunctions.size === 0 || delta != null, "You are trying to use a blocker on a POP navigation to a location " + "that was not created by @remix-run/router. This will fail silently in " + "production. This can happen if you are navigating outside the router " + @@ -2123,12 +2119,6 @@ export function createRouter(init: RouterInit): Router { if (blockerFunctions.get(key) !== fn) { blockerFunctions.set(key, fn); - if (activeBlocker == null) { - // This is now the active blocker - activeBlocker = key; - } else if (key !== activeBlocker) { - warning(false, "A router only supports one blocker at a time"); - } } return blocker; @@ -2137,9 +2127,6 @@ export function createRouter(init: RouterInit): Router { function deleteBlocker(key: string) { state.blockers.delete(key); blockerFunctions.delete(key); - if (activeBlocker === key) { - activeBlocker = null; - } } // Utility function to update blockers, ensuring valid state transitions @@ -2170,18 +2157,19 @@ export function createRouter(init: RouterInit): Router { nextLocation: Location; historyAction: HistoryAction; }): string | undefined { - if (activeBlocker == null) { + if (blockerFunctions.size === 0) { return; } - // We only allow a single blocker at the moment. This will need to be - // updated if we enhance to support multiple blockers in the future - let blockerFunction = blockerFunctions.get(activeBlocker); - invariant( - blockerFunction, - "Could not find a function for the active blocker" - ); - let blocker = state.blockers.get(activeBlocker); + // We ony support a single active blocker at the moment since we don't have + // any compelling use cases for multi-blocker yet + if (blockerFunctions.size > 1) { + warning(false, "A router only supports one blocker at a time"); + } + + let entries = Array.from(blockerFunctions.entries()); + let [blockerKey, blockerFunction] = entries[entries.length - 1]; + let blocker = state.blockers.get(blockerKey); if (blocker && blocker.state === "proceeding") { // If the blocker is currently proceeding, we don't need to re-check @@ -2192,7 +2180,7 @@ export function createRouter(init: RouterInit): Router { // At this point, we know we're unblocked/blocked so we need to check the // user-provided blocker function if (blockerFunction({ currentLocation, nextLocation, historyAction })) { - return activeBlocker; + return blockerKey; } }