From dd44191118461e44debb762c81d1383bd19416c4 Mon Sep 17 00:00:00 2001 From: Zack Tanner <1939140+ztanner@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:32:35 -0700 Subject: [PATCH] fix root page revalidation when redirecting in a server action (#64730) When a server action triggers a redirect, we're incorrectly applying a refresh marker to the segment they were on, rather than the segment they were being redirected to. As a result, when revalidation occurs (via `revalidateX` or `router.refresh()`), the top-level segment would be replaced with data for an incorrect segment. For example, if triggering a redirect action from `/redirect` to `/`, the router state tree would save a reference to `/redirect`. The next time a refresh or revalidate happens, it'd refresh the segment data for `/redirect` instead of `/`. Fixes #64728 Closes NEXT-3156 --- .../reducers/server-action-reducer.ts | 4 +++- .../app/actions.ts | 8 ++++++- .../parallel-routes-revalidation/app/page.tsx | 5 +++- .../app/redirect/page.tsx | 14 +++++++++++ .../parallel-routes-revalidation.test.ts | 23 +++++++++++++++++++ 5 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 test/e2e/app-dir/parallel-routes-revalidation/app/redirect/page.tsx diff --git a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts index 7d8e314b848ad..4784cfbdee5f7 100644 --- a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts @@ -225,7 +225,9 @@ export function serverActionReducer( [''], currentTree, treePatch, - href + redirectLocation + ? createHrefFromUrl(redirectLocation) + : state.canonicalUrl ) if (newTree === null) { diff --git a/test/e2e/app-dir/parallel-routes-revalidation/app/actions.ts b/test/e2e/app-dir/parallel-routes-revalidation/app/actions.ts index 465a4c417b0f4..dc194b76a78ef 100644 --- a/test/e2e/app-dir/parallel-routes-revalidation/app/actions.ts +++ b/test/e2e/app-dir/parallel-routes-revalidation/app/actions.ts @@ -1,7 +1,8 @@ 'use server' +import { revalidatePath } from 'next/cache' import { redirect } from 'next/navigation' -const data = [] +let data = [] export async function addData(newData: string) { // sleep 1s @@ -21,3 +22,8 @@ export async function redirectAction() { await new Promise((res) => setTimeout(res, 1000)) redirect('/') } + +export async function clearData() { + data = [] + revalidatePath('/') +} diff --git a/test/e2e/app-dir/parallel-routes-revalidation/app/page.tsx b/test/e2e/app-dir/parallel-routes-revalidation/app/page.tsx index b8f647cca09e0..3ef8e78993572 100644 --- a/test/e2e/app-dir/parallel-routes-revalidation/app/page.tsx +++ b/test/e2e/app-dir/parallel-routes-revalidation/app/page.tsx @@ -1,5 +1,5 @@ import Link from 'next/link' -import { getData } from './actions' +import { clearData, getData } from './actions' export default async function Home() { const data = await getData() @@ -14,6 +14,9 @@ export default async function Home() { Open Redirect Modal Intercepted Detail Page