Skip to content

Fix widget-layer connection for late-added layers#511

Merged
TimPurdum merged 5 commits intodevelopfrom
bug/258-sketch-layer-connection
Feb 12, 2026
Merged

Fix widget-layer connection for late-added layers#511
TimPurdum merged 5 commits intodevelopfrom
bug/258-sketch-layer-connection

Conversation

@TimPurdum
Copy link
Collaborator

Summary

  • Fix race condition where widgets (e.g., SketchWidget) that reference a layer via LayerId fail to connect when the layer is added to the map after the widget renders
  • Add OnParametersSet override to MapComponent to propagate Layer, View, LayerId, and JS module references from parent components
  • Make LayerId and UpdateGeoBlazorReferences virtual so widgets like SketchWidget can override them
  • Update MapView.OnAfterRenderAsync to detect widgets with a matching LayerId when a new layer is added, and re-invoke UpdateGeoBlazorReferences to establish the connection
  • Add Widget.UpdateGeoBlazorReferences override that triggers UpdateWidget() when a new layer is assigned, ensuring the JS-side widget is updated
  • Replace direct StateHasChanged() calls with InvokeAsync(StateHasChanged) in MapView for thread safety
  • Remove null-forgiving operators on JsComponentReference and CoreJsModule in Layer and Widget update methods

How this supports Pro SketchWidget changes

The Pro SketchWidget allows users to specify a GraphicsLayer by reference, by GraphicsLayerId, or via the base Layer/LayerId parameters. When a layer is added programmatically after the map renders (a common pattern), the widget previously had no way to discover its layer had become available.

These Core changes provide the infrastructure for that scenario:

  1. MapView detects late-added layers and notifies widgets whose LayerId matches
  2. Widget.UpdateGeoBlazorReferences triggers a JS-side updateComponent call when a new layer is assigned
  3. Virtual LayerId lets SketchWidget override it to sync with GraphicsLayerId
  4. OnParametersSet propagation ensures layer references flow down the component tree without requiring explicit wiring

The Pro SketchWidget overrides UpdateGeoBlazorReferences to sync GraphicsLayer from the incoming layer, then relies on the base Widget implementation to push the update to JavaScript.

Test plan

  • Verify SketchWidget works when GraphicsLayer is set as a direct child parameter
  • Verify SketchWidget works when GraphicsLayerId is set and the layer is added before the widget renders
  • Verify SketchWidget works when LayerId is set and the layer is added after the widget renders (the race condition fix)
  • Verify existing widget tests pass (no regressions from StateHasChangedInvokeAsync(StateHasChanged) change)
  • Run Core and Pro test suites

🤖 Generated with Claude Code

@claude
Copy link

claude bot commented Feb 12, 2026

Claude finished @TimPurdum's task —— View job


PR Review Analysis Complete

Todo List:

  • Read and analyze all changed files
  • Review race condition fix implementation
  • Check thread safety improvements
  • Review virtual method implementations
  • Provide actionable feedback

Review Summary

After thoroughly analyzing the 6 changed files, I found several issues that should be addressed:

Thread Safety Issue in MapView.cs

Line 283: Direct StateHasChanged() call should be InvokeAsync(StateHasChanged) for thread safety consistency

await InvokeAsync(StateHasChanged);

This is inconsistent with the other thread-safe changes in the same file.

Widget.cs - Potential Race Condition

Lines 457-470: The UpdateGeoBlazorReferences override creates a fire-and-forget task that could cause issues:

_ = Task.Run(async () => await UpdateWidget());

This approach doesn't handle exceptions and could create timing issues. Consider:

if (needsUpdate)
{
    _ = InvokeAsync(async () => await UpdateWidget());
}

MapComponent.cs - Missing Null Check

Line 894: Parent?.ProJsModule assignment could fail if Parent becomes null between the null check and property access in a multi-threaded scenario. Consider:

var parent = Parent;
ProJsModule ??= parent?.ProJsModule;

Version Increment Logic

Directory.Build.props: Version changed from 5.0.0.75 to 5.0.0.76 - ensure this increment is appropriate for the scope of changes.

Test File - Thread Safety

TestRunnerBase.cs Line 161: Missing InvokeAsync wrapper around StateHasChanged():

await InvokeAsync(StateHasChanged);

Overall Assessment

The race condition fix is well-designed and addresses the core issue effectively. The virtual LayerId property and OnParametersSet propagation provide solid infrastructure for late-layer binding. However, the thread safety improvements need to be applied consistently throughout all files.


@TimPurdum TimPurdum self-assigned this Feb 12, 2026
@TimPurdum TimPurdum merged commit 6cc554c into develop Feb 12, 2026
3 checks passed
@TimPurdum TimPurdum deleted the bug/258-sketch-layer-connection branch February 12, 2026 15:53
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.

1 participant

Comments