Skip to content

Commit

Permalink
fix refresh behavior for discarded actions
Browse files Browse the repository at this point in the history
  • Loading branch information
ztanner committed Apr 15, 2024
1 parent bde8951 commit 03dbfa6
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 14 deletions.
6 changes: 3 additions & 3 deletions packages/next/src/client/components/layout-router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -437,10 +437,10 @@ function InnerLayoutRouter({
// It's important that we mark this as resolved, in case this branch is replayed, we don't want to continously re-apply
// the patch to the tree.
childNode.lazyDataResolved = true
}

// Suspend infinitely as `changeByServerResponse` will cause a different part of the tree to be rendered.
use(unresolvedThenable) as never
// Suspend infinitely as `changeByServerResponse` will cause a different part of the tree to be rendered.
use(unresolvedThenable) as never
}
}

// If we get to this point, then we know we have something we can render.
Expand Down
24 changes: 13 additions & 11 deletions packages/next/src/shared/lib/router/action-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ function runRemainingActions(
action: actionQueue.pending,
setState,
})
} else {
// No more actions are pending, check if a refresh is needed
if (actionQueue.needsRefresh) {
actionQueue.needsRefresh = false
actionQueue.dispatch(
{
type: ACTION_REFRESH,
origin: window.location.origin,
},
setState
)
}
}
}
}
Expand Down Expand Up @@ -75,17 +87,7 @@ async function runAction({
function handleResult(nextState: AppRouterState) {
// if we discarded this action, the state should also be discarded
if (action.discarded) {
// if a refresh is needed, we only want to trigger it once the action queue is empty
if (actionQueue.needsRefresh && actionQueue.pending === null) {
actionQueue.needsRefresh = false
actionQueue.dispatch(
{
type: ACTION_REFRESH,
origin: window.location.origin,
},
setState
)
}
console.log('discarded an action')
return
}

Expand Down
25 changes: 25 additions & 0 deletions test/e2e/app-dir/actions/app-action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,31 @@ createNextDescribe(
}, 'success')
})

it('should trigger a refresh for a server action that also dispatches a navigation event', async () => {
let browser = await next.browser('/revalidate')
let initialJustPutit = await browser.elementById('justputit').text()

// this triggers a revalidate + redirect in a client component
await browser.elementById('redirect-revalidate-client').click()
await retry(async () => {
const newJustPutIt = await browser.elementById('justputit').text()
expect(newJustPutIt).not.toBe(initialJustPutit)

expect(await browser.url()).toBe(`${next.url}/revalidate?foo=bar`)
})

// this triggers a revalidate + redirect in a server component
browser = await next.browser('/revalidate')
initialJustPutit = await browser.elementById('justputit').text()
await browser.elementById('redirect-revalidate').click()
await retry(async () => {
const newJustPutIt = await browser.elementById('justputit').text()
expect(newJustPutIt).not.toBe(initialJustPutit)

expect(await browser.url()).toBe(`${next.url}/revalidate?foo=bar`)
})
})

it('should support next/dynamic with ssr: false', async () => {
const browser = await next.browser('/dynamic-csr')

Expand Down
18 changes: 18 additions & 0 deletions test/e2e/app-dir/actions/app/revalidate/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use client'

import { useRouter } from 'next/navigation'

export default function RedirectClientComponent({ action }) {
const router = useRouter()
return (
<button
id="redirect-revalidate-client"
onClick={async () => {
await action()
router.push('/revalidate?foo=bar')
}}
>
redirect + revalidate (client component)
</button>
)
}
19 changes: 19 additions & 0 deletions test/e2e/app-dir/actions/app/revalidate/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { redirect } from 'next/navigation'
import Link from 'next/link'

import { cookies } from 'next/headers'
import RedirectClientComponent from './client'

export default async function Page() {
const data = await fetch(
Expand Down Expand Up @@ -133,6 +134,24 @@ export default async function Page() {
redirect
</button>
</form>
<form>
<button
id="redirect-revalidate"
formAction={async () => {
'use server'
revalidateTag('justputit')
redirect('/revalidate?foo=bar')
}}
>
redirect + revalidate
</button>
</form>
<RedirectClientComponent
action={async () => {
'use server'
revalidateTag('justputit')
}}
/>
</>
)
}

0 comments on commit 03dbfa6

Please sign in to comment.