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

PR_039

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.
@MitchLewis930 MitchLewis930 requested a review from Copilot January 31, 2026 01:06
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR re-implements the Server Action reducer to align with the new segment cache navigation architecture. The implementation unifies action handling with regular navigation flows, treating Server Actions as seeded navigations that optionally include rendered data from the server response.

Changes:

  • Added renderedSearch and couldBeIntercepted fields to action and navigation flight responses
  • Refactored server action reducer to use the new navigateToSeededRoute navigation flow
  • Renamed refresh to navigateToSeededRoute to better reflect its general-purpose nature
  • Updated navigation functions to accept shouldRefreshDynamicData parameter

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/next/src/shared/lib/app-router-types.ts Added q (renderedSearch) and i (couldBeIntercepted) fields to flight response types
packages/next/src/server/app-render/app-render.tsx Included renderedSearch and couldBeIntercepted in RSC payload generation
packages/next/src/client/components/segment-cache/navigation.ts Refactored refresh function to navigateToSeededRoute with broader applicability
packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts Replaced custom action handling logic with unified navigation flows
packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts Updated to use navigateToSeededRoute with explicit parameters
packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts Added shouldRefreshDynamicData parameter to navigation call
packages/next/src/client/components/router-reducer/ppr-navigations.ts Added seedData and seedHead parameters throughout navigation functions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// since we keep them in sync anyway, but having two sources of truth can
// lead to subtle bugs and race conditions.
href === window.location.href
const isSamePageNavigation = href === currentUrl.href
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

The comparison uses href which is undefined at this point. The code should use url.href instead of href since the href variable hasn't been extracted from the url object yet.

Copilot uses AI. Check for mistakes.
Comment on lines +74 to +76
// TODO: Refactor to be a discriminated union. Or just get rid of it;
// fetchServerAction only has one caller, no reason this intermediate type has
// to exist.
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

This TODO comment appears to be new code but suggests removing or refactoring the type immediately below it. Consider addressing this before merging, as the comment indicates the current design may be suboptimal.

Suggested change
// TODO: Refactor to be a discriminated union. Or just get rid of it;
// fetchServerAction only has one caller, no reason this intermediate type has
// to exist.

Copilot uses AI. Check for mistakes.
Comment on lines +495 to +505
// Used to request all the dynamic data for a route, rather than just a subset,
// e.g. during a refresh or a revalidation. Typically this gets constructed
// during the normal flow when diffing the route tree, but for an unprefetched
// navigation, where we don't know the structure of the target route, we use
// this instead.
const DynamicRequestTreeForEntireRoute: FlightRouterState = [
'',
{},
null,
'refetch',
]
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

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

The constant name DynamicRequestTreeForEntireRoute is quite verbose. Consider shortening to FULL_DYNAMIC_REQUEST_TREE or REFETCH_TREE to improve readability while maintaining clarity.

Copilot uses AI. Check for mistakes.
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