Skip to content

Fix Blazor root component state persistence across render modes #62370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jun 17, 2025

Summary

This PR fixes state persistence for Blazor root components where the @key directive information was lost when transitioning between prerendering and interactive modes, causing different persistence keys to be generated.

Problem

The issue occurred because GetSerializableKey in SupplyParameterFromPersistentComponentStateValueProvider produced different values when rendering statically vs. interactively. During prerendering, the parent component hierarchy differed from interactive mode, leading to inconsistent key generation and failed state persistence for root components.

Solution

Core Changes

  1. Added ComponentState.GetComponentKey() - New protected virtual method that extracts @key directives from the parent component's render tree, providing a consistent interface across render modes.

  2. Enhanced EndpointComponentState - Overrides GetComponentKey() to detect SSRRenderModeBoundary components and return the ComponentMarkerKey for consistent root component identification.

  3. Specialized ComponentState subclasses - Created WebAssemblyComponentState and RemoteComponentState that accept ComponentMarkerKey parameters and return them from GetComponentKey() when available.

  4. Improved key computation - Moved ComputeKey logic to ComponentState with enhanced parent type filtering that excludes SSRRenderModeBoundary components from the hierarchy calculation.

  5. SSRRenderModeBoundary helper - Added GetComponentMarkerKey() method to expose the internal marker key for state persistence.

Key Algorithm

The solution ensures consistent key generation by:

  • Using the same ComputeKey algorithm across all render modes
  • Providing ComponentMarkerKey consistently for root components
  • Filtering out SSRRenderModeBoundary from parent type calculations
  • Maintaining serializable key validation

Example

Before this fix, a root component with state persistence would fail:

@rendermode InteractiveServer
<div>
    <p>Counter: @count</p>
    <button @onclick="Increment">Increment</button>
</div>

@code {
    [SupplyParameterFromPersistentComponentState]
    private int count { get; set; } = 0;

    private void Increment() => count++;
}

The count value would be lost during prerender-to-interactive transitions because different keys were generated in each mode. With this fix, the same key is used consistently, preserving the state.

Testing

  • Updated all existing tests to use the new ComponentState.ComputeKey() API
  • Added comprehensive validation for cross-render-mode key consistency
  • Maintained backward compatibility for the key generation algorithm
  • Verified proper ComponentMarkerKey integration

Fixes #62331.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copy link
Contributor

Greetings human! You've submitted a PR that modifies code that is shared with https://github.com/dotnet/runtime . Please make sure you synchronize this code with the changes in that repo!

@Copilot Copilot AI changed the title [WIP] [Blazor] Support state persistence on root components Fix Blazor root component state persistence across render modes Jun 17, 2025
@Copilot Copilot AI requested a review from javiercn June 17, 2025 11:38
Copilot finished work on behalf of javiercn June 17, 2025 11:39
@javiercn javiercn marked this pull request as ready for review June 17, 2025 17:28
@javiercn javiercn requested a review from a team as a code owner June 17, 2025 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Blazor] Support state persistence on root components
2 participants