Skip to content

Commit 5682527

Browse files
crisbetoatscott
authored andcommitted
fix(core): not all callbacks running when registered at the same time (#56981)
Fixes that only the first callback was firing when multiple are registered in the same call to `afterNextRender`, e.g. `afterNextRender({earlyRead: fn, read: fn});` Fixes #56979. PR Close #56981
1 parent 4c1f3cf commit 5682527

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

packages/core/src/render3/after_render_hooks.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ function afterRenderImpl(
598598
unregisterFn();
599599
};
600600
const unregisterFn = injector.get(DestroyRef).onDestroy(destroy);
601+
let callbacksLeftToRun = 0;
601602

602603
const registerCallback = (
603604
phase: AfterRenderPhase,
@@ -608,7 +609,10 @@ function afterRenderImpl(
608609
}
609610
const callback = once
610611
? (...args: [unknown]) => {
611-
destroy();
612+
callbacksLeftToRun--;
613+
if (callbacksLeftToRun < 1) {
614+
destroy();
615+
}
612616
phaseCallback(...args);
613617
}
614618
: phaseCallback;
@@ -619,6 +623,7 @@ function afterRenderImpl(
619623
);
620624
callbackHandler.register(instance);
621625
instances.push(instance);
626+
callbacksLeftToRun++;
622627
};
623628

624629
registerCallback(AfterRenderPhase.EarlyRead, spec.earlyRead);

packages/core/test/acceptance/after_render_hook_spec.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,87 @@ describe('after render hooks', () => {
12331233
'read-2',
12341234
]);
12351235
});
1236+
1237+
it('should invoke all the callbacks once when they are registered at the same time', () => {
1238+
const log: string[] = [];
1239+
1240+
@Component({template: ''})
1241+
class Comp {
1242+
constructor() {
1243+
afterNextRender({
1244+
earlyRead: () => {
1245+
log.push('early-read');
1246+
},
1247+
write: () => {
1248+
log.push('write');
1249+
},
1250+
mixedReadWrite: () => {
1251+
log.push('mixed-read-write');
1252+
},
1253+
read: () => {
1254+
log.push('read');
1255+
},
1256+
});
1257+
}
1258+
}
1259+
1260+
TestBed.configureTestingModule({
1261+
declarations: [Comp],
1262+
...COMMON_CONFIGURATION,
1263+
});
1264+
createAndAttachComponent(Comp);
1265+
1266+
expect(log).toEqual([]);
1267+
TestBed.inject(ApplicationRef).tick();
1268+
expect(log).toEqual(['early-read', 'write', 'mixed-read-write', 'read']);
1269+
TestBed.inject(ApplicationRef).tick();
1270+
expect(log).toEqual(['early-read', 'write', 'mixed-read-write', 'read']);
1271+
});
1272+
1273+
it('should invoke all the callbacks each time when they are registered at the same time', () => {
1274+
const log: string[] = [];
1275+
1276+
@Component({template: ''})
1277+
class Comp {
1278+
constructor() {
1279+
afterRender({
1280+
earlyRead: () => {
1281+
log.push('early-read');
1282+
},
1283+
write: () => {
1284+
log.push('write');
1285+
},
1286+
mixedReadWrite: () => {
1287+
log.push('mixed-read-write');
1288+
},
1289+
read: () => {
1290+
log.push('read');
1291+
},
1292+
});
1293+
}
1294+
}
1295+
1296+
TestBed.configureTestingModule({
1297+
declarations: [Comp],
1298+
...COMMON_CONFIGURATION,
1299+
});
1300+
createAndAttachComponent(Comp);
1301+
1302+
expect(log).toEqual([]);
1303+
TestBed.inject(ApplicationRef).tick();
1304+
expect(log).toEqual(['early-read', 'write', 'mixed-read-write', 'read']);
1305+
TestBed.inject(ApplicationRef).tick();
1306+
expect(log).toEqual([
1307+
'early-read',
1308+
'write',
1309+
'mixed-read-write',
1310+
'read',
1311+
'early-read',
1312+
'write',
1313+
'mixed-read-write',
1314+
'read',
1315+
]);
1316+
});
12361317
});
12371318

12381319
it('allows writing to a signal in afterRender', () => {

0 commit comments

Comments
 (0)