Skip to content

Commit 0c7c852

Browse files
devknollthePunderWoman
authored andcommitted
fix(core): run afterRender callbacks outside of the Angular zone (#51551)
afterRender should run outside of the Angular zone so that it does not trigger further CD cycles PR Close #51551
1 parent a06140a commit 0c7c852

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

packages/core/src/render3/after_render_hooks.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {assertInInjectionContext, Injector, ɵɵdefineInjectable} from '../di';
1010
import {inject} from '../di/injector_compatibility';
1111
import {RuntimeError, RuntimeErrorCode} from '../errors';
1212
import {DestroyRef} from '../linker/destroy_ref';
13+
import {NgZone} from '../zone';
1314

1415
import {isPlatformBrowser} from './util/misc_utils';
1516

@@ -91,7 +92,8 @@ export function afterRender(callback: VoidFunction, options?: AfterRenderOptions
9192
let destroy: VoidFunction|undefined;
9293
const unregisterFn = injector.get(DestroyRef).onDestroy(() => destroy?.());
9394
const manager = injector.get(AfterRenderEventManager);
94-
const instance = new AfterRenderCallback(callback);
95+
const ngZone = injector.get(NgZone);
96+
const instance = new AfterRenderCallback(() => ngZone.runOutsideAngular(callback));
9597

9698
destroy = () => {
9799
manager.unregister(instance);
@@ -155,9 +157,10 @@ export function afterNextRender(
155157
let destroy: VoidFunction|undefined;
156158
const unregisterFn = injector.get(DestroyRef).onDestroy(() => destroy?.());
157159
const manager = injector.get(AfterRenderEventManager);
160+
const ngZone = injector.get(NgZone);
158161
const instance = new AfterRenderCallback(() => {
159162
destroy?.();
160-
callback();
163+
ngZone.runOutsideAngular(callback);
161164
});
162165

163166
destroy = () => {

packages/core/test/acceptance/after_render_hook_spec.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {PLATFORM_BROWSER_ID, PLATFORM_SERVER_ID} from '@angular/common/src/platform_id';
10-
import {afterNextRender, afterRender, AfterRenderRef, ChangeDetectorRef, Component, inject, Injector, PLATFORM_ID, ViewContainerRef} from '@angular/core';
10+
import {afterNextRender, afterRender, AfterRenderRef, ChangeDetectorRef, Component, inject, Injector, NgZone, PLATFORM_ID, ViewContainerRef} from '@angular/core';
1111
import {TestBed} from '@angular/core/testing';
1212

1313
describe('after render hooks', () => {
@@ -225,6 +225,29 @@ describe('after render hooks', () => {
225225
expect(outerHookCount).toBe(3);
226226
expect(innerHookCount).toBe(2);
227227
});
228+
229+
it('should run outside of the Angular zone', () => {
230+
const zoneLog: boolean[] = [];
231+
232+
@Component({selector: 'comp'})
233+
class Comp {
234+
constructor() {
235+
afterRender(() => {
236+
zoneLog.push(NgZone.isInAngularZone());
237+
});
238+
}
239+
}
240+
241+
TestBed.configureTestingModule({
242+
declarations: [Comp],
243+
...COMMON_CONFIGURATION,
244+
});
245+
const fixture = TestBed.createComponent(Comp);
246+
247+
expect(zoneLog).toEqual([]);
248+
fixture.detectChanges();
249+
expect(zoneLog).toEqual([false]);
250+
});
228251
});
229252

230253
describe('afterNextRender', () => {
@@ -431,6 +454,29 @@ describe('after render hooks', () => {
431454
expect(outerHookCount).toBe(1);
432455
expect(innerHookCount).toBe(1);
433456
});
457+
458+
it('should run outside of the Angular zone', () => {
459+
const zoneLog: boolean[] = [];
460+
461+
@Component({selector: 'comp'})
462+
class Comp {
463+
constructor() {
464+
afterNextRender(() => {
465+
zoneLog.push(NgZone.isInAngularZone());
466+
});
467+
}
468+
}
469+
470+
TestBed.configureTestingModule({
471+
declarations: [Comp],
472+
...COMMON_CONFIGURATION,
473+
});
474+
const fixture = TestBed.createComponent(Comp);
475+
476+
expect(zoneLog).toEqual([]);
477+
fixture.detectChanges();
478+
expect(zoneLog).toEqual([false]);
479+
});
434480
});
435481
});
436482

packages/core/test/bundling/router/bundle.golden_symbols.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1980,7 +1980,7 @@
19801980
"name": "tap"
19811981
},
19821982
{
1983-
"name": "throwError5"
1983+
"name": "throwError2"
19841984
},
19851985
{
19861986
"name": "throwIfEmpty"

0 commit comments

Comments
 (0)