From eee72037c2577c93ee8078ad1dea8457d9b67894 Mon Sep 17 00:00:00 2001 From: Zack Tanner <1939140+ztanner@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:42:55 -0700 Subject: [PATCH] prevent erroneous route interception during lazy fetch --- .../src/client/components/layout-router.tsx | 4 ++- .../parallel-routes-revalidation.test.ts | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/packages/next/src/client/components/layout-router.tsx b/packages/next/src/client/components/layout-router.tsx index f66967cb973cd..6d945eb6477eb 100644 --- a/packages/next/src/client/components/layout-router.tsx +++ b/packages/next/src/client/components/layout-router.tsx @@ -33,6 +33,7 @@ import { RedirectBoundary } from './redirect-boundary' import { NotFoundBoundary } from './not-found-boundary' import { getSegmentValue } from './router-reducer/reducers/get-segment-value' import { createRouterCacheKey } from './router-reducer/create-router-cache-key' +import { hasInterceptionRouteInCurrentTree } from './router-reducer/reducers/has-interception-route-in-current-tree' /** * Add refetch marker to router state at the point of the current layout segment. @@ -408,10 +409,11 @@ function InnerLayoutRouter({ */ // TODO-APP: remove '' const refetchTree = walkAddRefetch(['', ...segmentPath], fullTree) + const includeNextUrl = hasInterceptionRouteInCurrentTree(fullTree) childNode.lazyData = lazyData = fetchServerResponse( new URL(url, location.origin), refetchTree, - context.nextUrl, + includeNextUrl ? context.nextUrl : null, buildId ) childNode.lazyDataResolved = false diff --git a/test/e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts b/test/e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts index a93659b858bf4..80ce5e68aa252 100644 --- a/test/e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts +++ b/test/e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts @@ -158,6 +158,39 @@ createNextDescribe( }) }) + it('should not trigger the intercepted route when lazy-fetching missing data', async () => { + const browser = await next.browser('/') + + // trigger the interception page + await browser.elementByCss("[href='/detail-page']").click() + + // we should see the intercepted page + expect(await browser.elementById('detail-title').text()).toBe( + 'Detail Page (Intercepted)' + ) + + // refresh the page + await browser.refresh() + + // we should see the detail page + expect(await browser.elementById('detail-title').text()).toBe( + 'Detail Page (Non-Intercepted)' + ) + + // go back to the previous page + await browser.back() + + // reload the page, which will cause the router to no longer have cache nodes + await browser.refresh() + + // go forward, this will trigger a lazy fetch for the missing data, and should restore the detail page + await browser.forward() + + expect(await browser.elementById('detail-title').text()).toBe( + 'Detail Page (Non-Intercepted)' + ) + }) + describe.each([ { basePath: '/refreshing', label: 'regular', withSearchParams: false }, { basePath: '/refreshing', label: 'regular', withSearchParams: true },