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 7d8e314b848ad1..4784cfbdee5f74 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 465a4c417b0f4a..dc194b76a78eff 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 b8f647cca09e0e..3ef8e789935721 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
{randomNumber}
+
Current Data
diff --git a/test/e2e/app-dir/parallel-routes-revalidation/app/redirect/page.tsx b/test/e2e/app-dir/parallel-routes-revalidation/app/redirect/page.tsx
new file mode 100644
index 00000000000000..f451ae9b3b5bca
--- /dev/null
+++ b/test/e2e/app-dir/parallel-routes-revalidation/app/redirect/page.tsx
@@ -0,0 +1,14 @@
+import { redirect } from 'next/navigation'
+
+export default function Page() {
+ return (
+
+ )
+}
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 80ce5e68aa2524..fb55d950a2db67 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
@@ -1,5 +1,5 @@
import { createNextDescribe } from 'e2e-utils'
-import { check, retry } from 'next-test-utils'
+import { check, retry, waitFor } from 'next-test-utils'
createNextDescribe(
'parallel-routes-revalidation',
@@ -191,6 +191,29 @@ createNextDescribe(
)
})
+ it('should refresh the correct page when a server action triggers a redirect', async () => {
+ const browser = await next.browser('/redirect')
+ await browser.elementByCss('button').click()
+
+ await browser.elementByCss("[href='/revalidate-modal']").click()
+
+ await check(() => browser.hasElementByCssSelector('#create-entry'), true)
+
+ await browser.elementById('clear-entries').click()
+
+ await retry(async () => {
+ // confirm there aren't any entries yet
+ expect((await browser.elementsByCss('#entries li')).length).toBe(0)
+ })
+
+ await browser.elementById('create-entry').click()
+
+ await retry(async () => {
+ // we created an entry and called revalidate, so we should have 1 entry
+ expect((await browser.elementsByCss('#entries li')).length).toBe(1)
+ })
+ })
+
describe.each([
{ basePath: '/refreshing', label: 'regular', withSearchParams: false },
{ basePath: '/refreshing', label: 'regular', withSearchParams: true },