diff --git a/packages/react-router/tests/loaders.test.tsx b/packages/react-router/tests/loaders.test.tsx index 8d8ea54e73..fc9e87b077 100644 --- a/packages/react-router/tests/loaders.test.tsx +++ b/packages/react-router/tests/loaders.test.tsx @@ -430,7 +430,7 @@ test('reproducer #4546', async () => { component: () => { return ( <> -
+
{ expect(fooPendingComponentOnMountMock).not.toHaveBeenCalled() }) +test('throw abortError from loader upon initial load with basepath', async () => { + window.history.replaceState(null, 'root', '/app') + const rootRoute = createRootRoute({}) + + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + loader: async () => { + return Promise.reject(new DOMException('Aborted', 'AbortError')) + }, + component: () =>
Index route content
, + errorComponent: () => ( +
indexErrorComponent
+ ), + }) + + const routeTree = rootRoute.addChildren([indexRoute]) + const router = createRouter({ routeTree, history, basepath: '/app' }) + + render() + + const indexElement = await screen.findByText('Index route content') + expect(indexElement).toBeInTheDocument() + expect(screen.queryByTestId('index-error')).not.toBeInTheDocument() + expect(window.location.pathname.startsWith('/app')).toBe(true) +}) + test('cancelMatches after pending timeout', async () => { function getPendingComponent(onMount: () => void) { const PendingComponent = () => { diff --git a/packages/router-core/src/load-matches.ts b/packages/router-core/src/load-matches.ts index ec72cbfe44..87cb9ce34a 100644 --- a/packages/router-core/src/load-matches.ts +++ b/packages/router-core/src/load-matches.ts @@ -699,6 +699,15 @@ const runLoader = async ( } catch (e) { let error = e + if ((error as any)?.name === 'AbortError') { + inner.updateMatch(matchId, (prev) => ({ + ...prev, + status: prev.status === 'pending' ? 'success' : prev.status, + isFetching: false, + })) + return + } + const pendingPromise = match._nonReactive.minPendingPromise if (pendingPromise) await pendingPromise diff --git a/packages/solid-router/tests/loaders.test.tsx b/packages/solid-router/tests/loaders.test.tsx index c0e5253219..09f1676bd8 100644 --- a/packages/solid-router/tests/loaders.test.tsx +++ b/packages/solid-router/tests/loaders.test.tsx @@ -320,6 +320,33 @@ test('throw error from beforeLoad when navigating to route', async () => { expect(indexElement).toBeInTheDocument() }) +test('throw abortError from loader upon initial load with basepath', async () => { + window.history.replaceState(null, 'root', '/app') + const rootRoute = createRootRoute({}) + + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + loader: async () => { + return Promise.reject(new DOMException('Aborted', 'AbortError')) + }, + component: () =>
Index route content
, + errorComponent: () => ( +
indexErrorComponent
+ ), + }) + + const routeTree = rootRoute.addChildren([indexRoute]) + const router = createRouter({ routeTree, basepath: '/app' }) + + render(() => ) + + const indexElement = await screen.findByText('Index route content') + expect(indexElement).toBeInTheDocument() + expect(screen.queryByTestId('index-error')).not.toBeInTheDocument() + expect(window.location.pathname.startsWith('/app')).toBe(true) +}) + test('reproducer #4245', async () => { const LOADER_WAIT_TIME = 500 const rootRoute = createRootRoute({})