Skip to content

fix(reconciler): re-render context consumers behind reference-stable child skips (#811)#812

Open
nsreehari wants to merge 3 commits into
microsoft:mainfrom
nsreehari:nsreehari/issue-811-context-consumer-skip
Open

fix(reconciler): re-render context consumers behind reference-stable child skips (#811)#812
nsreehari wants to merge 3 commits into
microsoft:mainfrom
nsreehari:nsreehari/issue-811-context-consumer-skip

Conversation

@nsreehari

Copy link
Copy Markdown

Bug: pure context changes lost behind reference-stable child skip paths

Fixes #811.

Root cause

A UseContext consumer nested inside a reference-stable subtree stopped
re-rendering on pure context changes. When a parent re-rendered with a changed
provider value but returned the same child Element instance, the
reconciler's shallow-equality fast paths short-circuited before descending
into the consumer, so HasConsumedContextChanged was never consulted. The
consumer kept rendering the stale context value, and event handlers it created
captured that stale value.

The skip was reachable at two independent layers, so a single-site fix was
insufficient (verified: removing either guard re-breaks the repro).

Fix

Both skip fast paths are now context-aware:

  • Reconciler.Update.cs — before the element-level ShallowEquals skip,
    decline the skip when a consumed context value changed in the subtree.
  • ChildReconciler.cs (UpdateCommonChild) — before the per-child
    CanSkipUpdate skip, run the same check and fall through to a real update.

Both are gated by the new ContextScope.HasActiveValues so no subtree walk
happens when no provider is active, and are driven by
Reconciler.HasConsumedContextChangedInSubtree(control), which checks the
control's ComponentNode and recurses via ForEachReactorChildControl.

Tests

New self-test regression fixture
Issue811ContextConsumerSkipFixtures.ReferenceStableChildSkip_ContextConsumerRerenders
(registered in SelfTestFixtureRegistry) covering mount, provider-toggle
re-render, and current-vs-stale context use from an event handler.

Validation

  • Focused host selftest Issue811_ReferenceStableChildSkip_ContextConsumerRerenders: 8/8 checks pass.
  • Reactor.Tests slice (ChildReconcilerStructuralSkip, ContextSystemSelfHost, MemoizationSelfHost, ComponentModelIntegration): 56 passed / 0 failed.
  • Full Reactor.SelfTests batch: passed.

…child skips

A component that consumes context via UseContext could stop updating when
it lived inside a reference-stable subtree. When a parent re-rendered with
a changed provider value but handed back the *same* child Element instance,
the reconciler's shallow-equality fast paths short-circuited the update
before descending into the consumer, so HasConsumedContextChanged was never
consulted and the consumer kept rendering its stale context value (and stale
event handlers captured the stale value).

The skip could be swallowed at two independent layers, so both are now
context-aware:

- Reconciler.Update.cs: before taking the element-level ShallowEquals skip,
  decline the skip when a consumed context value in the subtree changed.
- ChildReconciler.cs (UpdateCommonChild): before taking the per-child
  CanSkipUpdate skip, perform the same check and fall through to a real
  update when consumed context changed.

Both checks are gated by ContextScope.HasActiveValues so the subtree walk is
skipped entirely when no provider is active, and driven by the new
Reconciler.HasConsumedContextChangedInSubtree(control), which tests the
control's ComponentNode and recurses through ForEachReactorChildControl.

Adds a self-test regression fixture (Issue811ContextConsumerSkipFixtures)
covering mount, provider toggle re-render, and current-vs-stale context use
from an event handler, registered in SelfTestFixtureRegistry.

Validation:
- Focused host selftest Issue811_ReferenceStableChildSkip_ContextConsumerRerenders: 8/8 checks pass.
- Reactor.Tests slice (ChildReconcilerStructuralSkip, ContextSystemSelfHost, MemoizationSelfHost, ComponentModelIntegration): 56 passed, 0 failed.
- Full Reactor.SelfTests batch: passed.

Fixes microsoft#811
Sree Hari Nagaralu added 2 commits July 3, 2026 03:09
…-context-consumer-skip

# Conflicts:
#	tests/Reactor.AppTests.Host/SelfTest/SelfTestFixtureRegistry.cs
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.

Bug: pure context changes can be lost behind reference-stable child skip paths

1 participant