Skip to content

Fix Blazor persistent component state restoration for components without keys and add E2E test coverage #63194

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

Merged
merged 13 commits into from
Aug 15, 2025

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Aug 8, 2025

The _ignoreComponentPropertyValue flag in PersistentValueProviderComponentSubscription was only being set conditionally within if (!skipNotifications) blocks, causing restored values to be ignored when components are destroyed and re-added during navigation or when components don't use @key.

Problem

When a component is added, removed, then added again (for example, during page navigation or when a component doesn't use @key), the restored value from persistent state storage was being ignored. This happened because:

  1. During initial component setup, skipNotifications is often true
  2. The _ignoreComponentPropertyValue = true assignment was inside the if (!skipNotifications) block
  3. Without this flag set, GetOrComputeLastValue() would return the component's current property value instead of the restored value

Solution

Moved _ignoreComponentPropertyValue = true; outside the conditional blocks so it's set unconditionally whenever we successfully restore from persistent state. This ensures that the restored value always takes precedence over the component's initial property value, regardless of notification settings.

Before:

if (!skipNotifications)
{
    _ignoreComponentPropertyValue = true;
    _subscriber.NotifyCascadingValueChanged(ParameterViewLifetime.Unbound);
}

After:

_ignoreComponentPropertyValue = true;
if (!skipNotifications)
{
    _subscriber.NotifyCascadingValueChanged(ParameterViewLifetime.Unbound);
}

Test Coverage

Added comprehensive test coverage including:

Unit Tests

  • Enhanced existing unit tests to properly simulate cascading parameter behavior
  • Added debug test to verify the _ignoreComponentPropertyValue flag behavior
  • Fixed test timing issues by ensuring proper state consumption patterns

E2E Tests

Following feedback from @javiercn, added E2E test infrastructure for two critical scenarios:

  1. PageWithConditionalPersistentComponents.razor - New test page supporting:

    • Component without @key that always renders (tests navigation scenarios)
    • Component conditionally rendered based on query parameters (tests add/remove scenarios)
  2. StatePersistenceTest.cs - New E2E tests covering:

    • CanRestoreStateForComponentsWithoutKeysAndConditionalRendering - Validates both components restore state correctly
    • CanRestoreStateAfterConditionalComponentToggling - Tests state restoration after component toggling

The E2E tests use query string parameters to control component rendering and validate that persistent state works correctly in all scenarios where components are dynamically added/removed, particularly during enhanced navigation in Blazor applications.

Fixes #63193.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@Copilot Copilot AI changed the title [WIP] [Blazor] Persist component enhanced navigation state issue on components added or components updated without key Fix Blazor persistent component state restoration for components without keys Aug 8, 2025
@Copilot Copilot AI requested a review from javiercn August 8, 2025 17:18
Copilot finished work on behalf of javiercn August 8, 2025 17:18
@javiercn
Copy link
Member

javiercn commented Aug 8, 2025

@copilot

We should look at the E2E test cases in #62824 to add also support for these other two scenarios.

Specifically src/Components/test/E2ETest/Tests/StatePersistenceTest.cs and src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/PersistentState/PageWithDeclarativeEnhancedNavigationPersistentComponents.razor

Our test could be designed to use a query string to choose to render or not render the components. There would be one component without a key that renders always and a component that gets added/removed depending on the value of the query string.

In both cases the state should be restored successfully

Copy link
Contributor Author

Copilot AI commented Aug 8, 2025

@copilot

We should look at the E2E test cases in #62824 to add also support for these other two scenarios.
...

I've added E2E test support for the two scenarios you mentioned:

  1. PageWithConditionalPersistentComponents.razor - A new test page that uses query parameters to control component rendering:

    • Always-rendered component without @key (tests navigation scenarios)
    • Conditionally-rendered component based on show-conditional query parameter (tests add/remove scenarios)
  2. StatePersistenceTest.cs - New E2E tests:

    • CanRestoreStateForComponentsWithoutKeysAndConditionalRendering - Tests both components restore state correctly
    • CanRestoreStateAfterConditionalComponentToggling - Tests state restoration after toggling components on/off

The page follows the same pattern as the existing declarative enhanced navigation page, with links in PageWithoutComponents.razor for navigation. Both scenarios should validate that persistent state restoration works correctly regardless of when components are destroyed and recreated.

Implemented in 6b82560.

@Copilot Copilot AI changed the title Fix Blazor persistent component state restoration for components without keys Fix Blazor persistent component state restoration for components without keys and add E2E test coverage Aug 8, 2025
Copilot finished work on behalf of javiercn August 8, 2025 21:07
@javiercn javiercn marked this pull request as ready for review August 14, 2025 22:05
@Copilot Copilot AI review requested due to automatic review settings August 14, 2025 22:05
@javiercn javiercn requested a review from a team as a code owner August 14, 2025 22:05
Copy link
Contributor

@Copilot 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 fixes a bug in Blazor's persistent component state restoration where restored values were being ignored for components without @key attributes or during navigation scenarios. The core issue was that the _ignoreComponentPropertyValue flag was only being set conditionally within notification blocks, causing restored values to be overridden by component property values when notifications were skipped.

Key changes:

  • Moved the _ignoreComponentPropertyValue = true assignment outside conditional notification blocks to ensure it's always set when state is restored
  • Added comprehensive E2E test infrastructure with a new test page for conditional component rendering scenarios
  • Enhanced existing unit tests to better validate the flag behavior

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
PersistentValueProviderComponentSubscription.cs Core fix - moves the _ignoreComponentPropertyValue = true assignment outside conditional blocks
PageWithConditionalPersistentComponents.razor New test page supporting conditional component rendering scenarios
PageWithoutComponents.razor Updated navigation links and added support for new test scenarios
PageWithDeclarativeEnhancedNavigationPersistentComponents.razor Enhanced to support components with and without @key attributes
StatePersistenceTest.cs Updated existing E2E tests to support new test parameters
PersistentValueProviderComponentSubscriptionTests.cs Enhanced unit tests with better validation of state restoration behavior

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

…onents/Pages/PersistentState/PageWithoutComponents.razor
@javiercn javiercn merged commit 56ecd59 into main Aug 15, 2025
29 checks passed
@javiercn javiercn deleted the copilot/fix-63193 branch August 15, 2025 08:51
@dotnet-policy-service dotnet-policy-service bot added this to the 10.0-rc1 milestone Aug 15, 2025
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] Persist component enhanced navigation state issue on components added or components updated without key
3 participants