Skip to content

Commit d69dadb

Browse files
committed
feat: add blocker support for external URL navigation with ignoreBlocker option
1 parent 692d685 commit d69dadb

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

packages/react-router/tests/useBlocker.test.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { z } from 'zod'
77
import {
88
RouterProvider,
99
createBrowserHistory,
10+
createMemoryHistory,
1011
createRootRoute,
1112
createRoute,
1213
createRouter,
@@ -563,4 +564,33 @@ describe('useBlocker', () => {
563564

564565
expect(window.location.pathname).toBe('/non-existent')
565566
})
567+
568+
test('navigate function should handle external URLs with ignoreBlocker', async () => {
569+
const rootRoute = createRootRoute()
570+
const indexRoute = createRoute({
571+
getParentRoute: () => rootRoute,
572+
path: '/',
573+
component: () => <div>Home</div>,
574+
})
575+
576+
const router = createRouter({
577+
routeTree: rootRoute.addChildren([indexRoute]),
578+
history: createMemoryHistory({
579+
initialEntries: ['/'],
580+
}),
581+
})
582+
583+
await expect(
584+
router.navigate({
585+
to: 'https://example.com',
586+
ignoreBlocker: true,
587+
}),
588+
).resolves.toBeUndefined()
589+
590+
await expect(
591+
router.navigate({
592+
to: 'https://example.com',
593+
}),
594+
).resolves.toBeUndefined()
595+
})
566596
})

packages/router-core/src/router.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1778,7 +1778,7 @@ export class RouterCore<
17781778
})
17791779
}
17801780

1781-
navigate: NavigateFn = ({ to, reloadDocument, href, ...rest }) => {
1781+
navigate: NavigateFn = async ({ to, reloadDocument, href, ...rest }) => {
17821782
if (!reloadDocument && href) {
17831783
try {
17841784
new URL(`${href}`)
@@ -1791,6 +1791,26 @@ export class RouterCore<
17911791
const location = this.buildLocation({ to, ...rest } as any)
17921792
href = this.history.createHref(location.href)
17931793
}
1794+
1795+
// Check blockers for external URLs unless ignoreBlocker is true
1796+
if (!rest.ignoreBlocker) {
1797+
// Cast to access internal getBlockers method
1798+
const historyWithBlockers = this.history as any
1799+
const blockers = historyWithBlockers.getBlockers?.() ?? []
1800+
for (const blocker of blockers) {
1801+
if (blocker?.blockerFn) {
1802+
const shouldBlock = await blocker.blockerFn({
1803+
currentLocation: this.latestLocation,
1804+
nextLocation: this.latestLocation, // External URLs don't have a next location in our router
1805+
action: 'PUSH',
1806+
})
1807+
if (shouldBlock) {
1808+
return Promise.resolve()
1809+
}
1810+
}
1811+
}
1812+
}
1813+
17941814
if (rest.replace) {
17951815
window.location.replace(href)
17961816
} else {

0 commit comments

Comments
 (0)