Skip to content

[Validation] Analyzer diagnostics for unnecessary StateHasChanged calls #68484

Description

@oroztocil

Scenario contact: @ilonatommy

Scenario

Developers add StateHasChanged defensively, in places where ComponentBase already schedules a render. The calls are harmless but misleading, and they hide the few places a render really does need requesting. This validates that the build points them out, that the offered fix is safe to apply, and that genuinely necessary calls are left alone.

Minimum build

.NET 11 Preview 7 or later.

Configurations to cover

  • Blazor Web App
    • Static SSR
    • Interactive Server
    • Interactive WebAssembly
    • Interactive Auto
  • Standalone WebAssembly
  • Hybrid (MAUI)

These diagnostics are produced by the compiler, so they do not vary by render mode. The configuration below is the one needed to reproduce the runtime behavior the warning predicts, not a matrix to work through.

Also exercise

  • Published output
  • An existing .NET 10 app upgraded to .NET 11
  • Trimming or ahead-of-time compilation
  • More than one server instance, or a proxy in front
  • Hot Reload
  • An IDE as well as the command line
  • Container

Setup

Id Title Code fix
BL0012 Unnecessary StateHasChanged call Yes

The diagnostic covers synchronous lifecycle methods and event handlers, and in asynchronous ones the calls before the first await and after the final await.

What to build

A component that calls StateHasChanged in each of the places the diagnostic describes:

  • At the end of a synchronous event handler.
  • In OnInitialized, the synchronous lifecycle method.
  • In OnInitializedAsync, before the first await.
  • In OnParametersSetAsync, after the final await.

Alongside them, include the case that genuinely needs it: a call between two awaits in an async method, where the first await does not complete synchronously and the UI must update before the second finishes. Also add one from a timer or other callback that ComponentBase knows nothing about.

Things to try

  • Building at the command line and in an IDE, and comparing what each reports.
  • Applying the offered fix and rebuilding.
  • Running the app afterwards to confirm the UI still updates everywhere it did before.
  • Moving a call from between two awaits to after the last one, to see the warning appear.
  • Adding a second await to a method that had one, to see the warning disappear where the call becomes necessary.

Expected behavior

Only the unnecessary calls are flagged, and removing them changes nothing the user can see.

Must hold

  • Each unnecessary call produces a BL0012 warning naming the method it is in, in all four places above.
  • The call between two awaits, and the one from an external callback, produce no warning.
  • Applying the fix removes only the flagged call and leaves code that compiles.
  • After applying every fix, the UI still updates everywhere it did before.
  • The warnings appear both at the command line and in the IDE, at the same lines.

Expected differences between configurations

  • None. The warning is produced at compile time and is identical in every configuration.

Documentation to use

What to report

Report results using the format described in the validation testing manual. Include link to a repository with the test app.

Metadata

Metadata

Labels

ValidationThis issue is used to track validation effortsarea-blazorIncludes: Blazor, Razor Componentsvalidation-scenarioThis issue describes a validation testing scenario

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions