Skip to content

Comments

Re-implement Server Action reducer (#86367)#9

Open
MitchLewis930 wants to merge 1 commit intopr_039_beforefrom
pr_039_after
Open

Re-implement Server Action reducer (#86367)#9
MitchLewis930 wants to merge 1 commit intopr_039_beforefrom
pr_039_after

Conversation

@MitchLewis930
Copy link

@MitchLewis930 MitchLewis930 commented Jan 30, 2026

PR_039


Note

Medium Risk
Touches core client routing/server-action/refresh flows and changes how dynamic refetching and redirects are modeled, which can affect navigation correctness and cache consistency (especially with interception routes).

Overview
Reworks Server Action handling to drive updates through the Segment Cache navigation path. The serverActionReducer now decides between no-op, external redirect (MPA), seeded navigation (using Flight tree/seedData/head from the action response), or a normal segment-cache navigation, and it refreshes dynamic data when the action revalidated cache.

Refreshes are re-modeled as navigateToSeededRoute(...) with shouldRefreshDynamicData=true and interception-aware nextUrl selection.

Navigation internals were extended to support seeded data/head (favoring action-provided RSC/head over separate fetches), pass an explicit shouldRefreshDynamicData flag through navigation, and request full-route dynamic data for unprefetched refresh/revalidation cases.

Server RSC payloads now include q (rendered search) and i (could-be-intercepted) for both navigation and action responses, and the client consumes these to seed navigations correctly.

Written by Cursor Bugbot for commit e760fa2. This will update automatically on new commits. Configure here.

Rewrite of the Server Action reducer to use the PPR/Segment Cache
navigation implementation, rather than the old lazy fetch
implementation.

Server Actions may trigger a revalidation, a redirect, or both. They may
also invalidate the cache. The behavior could be naively implemented
using router.refresh() and router.push(). Semantically, the routing
behavior is equivalent.

The main difference is that the server that invokes the action may also
send back new data for the page within the same response. Compared to a
separate request, this data is more likely to be consistent with any
data that may have been mutated by the action, due to global data
propagation races. (It's also faster since it avoids an extra server
waterfall.)

So, navigations initiated by a Server action must be able to "seed" the
navigation with the data it just received from the server. I've added a
new internal method, navigateToSeededRoute, that implements this
behavior.
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

return handleMutable(state, mutable)
const pendingPush = redirectType !== RedirectType.replace
state.pushRef.pendingPush = pendingPush
mutable.pendingPush = pendingPush
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect pendingPush when action has no redirect

Medium Severity

When a server action triggers revalidation but no redirect, pendingPush is incorrectly set to true. The calculation redirectType !== RedirectType.replace evaluates to true when redirectType is undefined (no redirect occurred). This causes the router to push a new history entry when navigating after a revalidation-only action, potentially creating duplicate history entries for the same URL. The fix is to only set pendingPush to true when there's an actual redirect that isn't a replace — e.g., redirectLocation !== undefined && redirectType !== RedirectType.replace.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants