fix(reconciler): re-render context consumers behind reference-stable child skips (#811)#812
Open
nsreehari wants to merge 3 commits into
Open
Conversation
…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
added 2 commits
July 3, 2026 03:09
…-context-consumer-skip # Conflicts: # tests/Reactor.AppTests.Host/SelfTest/SelfTestFixtureRegistry.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug: pure context changes lost behind reference-stable child skip paths
Fixes #811.
Root cause
A
UseContextconsumer nested inside a reference-stable subtree stoppedre-rendering on pure context changes. When a parent re-rendered with a changed
provider value but returned the same child
Elementinstance, thereconciler's shallow-equality fast paths short-circuited before descending
into the consumer, so
HasConsumedContextChangedwas never consulted. Theconsumer 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-levelShallowEqualsskip,decline the skip when a consumed context value changed in the subtree.
ChildReconciler.cs(UpdateCommonChild) — before the per-childCanSkipUpdateskip, run the same check and fall through to a real update.Both are gated by the new
ContextScope.HasActiveValuesso no subtree walkhappens when no provider is active, and are driven by
Reconciler.HasConsumedContextChangedInSubtree(control), which checks thecontrol's
ComponentNodeand recurses viaForEachReactorChildControl.Tests
New self-test regression fixture
Issue811ContextConsumerSkipFixtures.ReferenceStableChildSkip_ContextConsumerRerenders(registered in
SelfTestFixtureRegistry) covering mount, provider-togglere-render, and current-vs-stale context use from an event handler.
Validation
Issue811_ReferenceStableChildSkip_ContextConsumerRerenders: 8/8 checks pass.Reactor.Testsslice (ChildReconcilerStructuralSkip,ContextSystemSelfHost,MemoizationSelfHost,ComponentModelIntegration): 56 passed / 0 failed.Reactor.SelfTestsbatch: passed.