Skip to content

App Router action queue: re-render final state when a pending action is preempted by navigation (fix stale data after revalidation) #2897

Description

@github-actions

Upstream change

Next.js 1e113cf — "Fix stale data after navigation despite revalidation" (#95439)

The bug

The App Router action queue always updates React state in dispatch order. When a navigation displaces (preempts) a pending server action, the navigation's promise is the last one dispatched. So when the preempted action later runs — even if it revalidated data — its resulting state is no longer reflected on screen, because the navigation's state was published last. Result: the UI shows stale data after navigation despite a successful revalidation.

The fix

In packages/next/src/client/components/app-router-instance.ts:

  • Add a wasPreempted?: boolean flag to AppRouterActionQueue.
  • When a pending action is discarded because a navigation takes priority (actionQueue.pending.discarded = true), also set actionQueue.wasPreempted = true.
  • In runRemainingActions, once the queue is idle (pending === null) and wasPreempted was set, clear the flag and publish the final queue state: startTransition(() => setState(actionQueue.state)). The existing needsRefresh flush now runs alongside this.

Why it's relevant to vinext

vinext reimplements App Router client-side navigation and the server-actions dispatch queue. If vinext's action queue does not re-render the final state after a preempting navigation, users will see stale data after a navigation that interrupts a revalidating action — matching the upstream bug.

Action

  • Check vinext's App Router action-queue implementation for equivalent preemption handling (navigation displacing a pending action).
  • Ensure the final queue state is re-published once the queue drains after a preemption, so revalidated data is reflected.
  • Port the regression test (actions-discarded-navigation-revert) which was red before the fix.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    nextjs-trackingTracking issue for a Next.js canary change relevant to vinext

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions