@@ -13,6 +13,7 @@ import {
1313 consumerPollProducersForChange ,
1414 getActiveConsumer ,
1515 ReactiveNode ,
16+ setActiveConsumer ,
1617} from '../../../primitives/signals' ;
1718
1819import { RuntimeError , RuntimeErrorCode } from '../../errors' ;
@@ -207,7 +208,10 @@ export function refreshView<T>(
207208 } else if ( getActiveConsumer ( ) === null ) {
208209 // If the current view should not have a reactive consumer but we don't have an active consumer,
209210 // we still need to create a temporary consumer to track any signal reads in this template.
210- // This is a rare case that can happen with `viewContainerRef.createEmbeddedView(...).detectChanges()`.
211+ // This is a rare case that can happen with
212+ // - `viewContainerRef.createEmbeddedView(...).detectChanges()`.
213+ // - `viewContainerRef.createEmbeddedView(...)` without any other dirty marking on the parent,
214+ // flagging the parent component for traversal but not triggering a full `refreshView`.
211215 // This temporary consumer marks the first parent that _should_ have a consumer for refresh.
212216 // Once that refresh happens, the signals will be tracked in the parent consumer and we can destroy
213217 // the temporary one.
@@ -490,16 +494,22 @@ function detectChangesInView(lView: LView, mode: ChangeDetectionMode) {
490494 if ( shouldRefreshView ) {
491495 refreshView ( tView , lView , tView . template , lView [ CONTEXT ] ) ;
492496 } else if ( flags & LViewFlags . HasChildViewsToRefresh ) {
493- if ( ! isInCheckNoChangesPass ) {
494- runEffectsInView ( lView ) ;
495- }
496- detectChangesInEmbeddedViews ( lView , ChangeDetectionMode . Targeted ) ;
497- const components = tView . components ;
498- if ( components !== null ) {
499- detectChangesInChildComponents ( lView , components , ChangeDetectionMode . Targeted ) ;
500- }
501- if ( ! isInCheckNoChangesPass ) {
502- addAfterRenderSequencesForView ( lView ) ;
497+ // Set active consumer to null to avoid inheriting an improper reactive context
498+ const prevConsumer = setActiveConsumer ( null ) ;
499+ try {
500+ if ( ! isInCheckNoChangesPass ) {
501+ runEffectsInView ( lView ) ;
502+ }
503+ detectChangesInEmbeddedViews ( lView , ChangeDetectionMode . Targeted ) ;
504+ const components = tView . components ;
505+ if ( components !== null ) {
506+ detectChangesInChildComponents ( lView , components , ChangeDetectionMode . Targeted ) ;
507+ }
508+ if ( ! isInCheckNoChangesPass ) {
509+ addAfterRenderSequencesForView ( lView ) ;
510+ }
511+ } finally {
512+ setActiveConsumer ( prevConsumer ) ;
503513 }
504514 }
505515}
0 commit comments