fix(ui/treeview): union sessionStorage keys instead of overwriting

The previous fix tried to defer page-side RevealNode to the second
render so TreeView's async sessionStorage load could finish first. In
practice Blazor Server didn't always fire a second OnAfterRenderAsync
on the page after the deep-link load, so the reveal never ran.

Real fix: change TreeView's storage-load to UNION the restored keys
with whatever's already in _expandedKeys, instead of REPLACING. That
way the page can call RevealNode whenever it wants and the storage
restore can't clobber the reveal regardless of completion order. The
page-side guard simplifies back to a one-shot reveal on first render.

Semantic note: if a deep-link reveal expands an ancestor that the user
had previously collapsed, the deep link wins. Intentional — the URL
expresses the navigation intent.
This commit is contained in:
Joseph Doherty
2026-05-11 12:42:38 -04:00
parent d8e6f44616
commit f3b33e7e1d
2 changed files with 5 additions and 4 deletions

View File

@@ -181,9 +181,7 @@
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Wait until second render so TreeView has finished restoring its sessionStorage
// expansion state; otherwise that restore races with RevealNode and overwrites it.
if (!_revealApplied && !firstRender && TemplateIdParam > 0 && _tree != null)
if (!_revealApplied && TemplateIdParam > 0 && _tree != null)
{
_revealApplied = true;
await _tree.RevealNode($"t:{TemplateIdParam}", select: true);

View File

@@ -127,7 +127,10 @@ else
var keys = System.Text.Json.JsonSerializer.Deserialize<List<string>>(json);
if (keys != null)
{
_expandedKeys = new HashSet<string>(keys);
// Union (don't replace): callers may have invoked RevealNode before
// this async storage load completed. Preserving those reveal-added
// keys ensures deep-link reveal isn't clobbered by the restore.
foreach (var k in keys) _expandedKeys.Add(k);
_initialExpansionApplied = true;
}
}