-
-
Notifications
You must be signed in to change notification settings - Fork 204
RxFor destroys/recreates DOM on long initial rendering, despite Angular non-destructive hydration was enabled #1867
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Known local workaroundIn the app I can add the Input renderCallback to the RxFor loop and tell Angular's PendingTasks class (which is still in Developer Preview phase) to wait until the rendering is done. *rxFor=".....; renderCallback: itemsRendered" itemsRendered = new Subject<Person[]>();
pendingTasks = inject(PendingTasks);
ngOnInit() {
// Tell Angular to wait with considering the app as "stable"
// until RxFor tells that all the items were rendered
this.pendingTasks.run(() => firstValueFrom(this.itemsRendered));
} See full commit on my Idea for solution inside RxAngular framework:For better DX, instead of me explicitly binding the RxFor's renderCallback to Angukar's PendingTasks in each and every of my components that use RxFor, ideally RxAngular library should bind them together under the hood in each instance of RxFor (and RxLet I guess too? and other directives that schedule rendering asynchronously). Such a DX improvent is even more important, when I'd have nested *rxFor loops in a single component's HTML template - then for my workaround I'd need manually to create renderCallbacks for each and every nested rxFor instance myself and then wait for completion of each of them. Analisys of Angular source code that led to those ideasFor reference, see also Angular's source code:
Note: let's not confuse Browser's macro tasks with Angular's tasks mentioned above. Angular's PendingTasks are just a list of "todo" jobs that needs to be finished until Angular considers the app to be stable. |
FYI: I've created a feature request in Angular repo to promote |
angular/angular#60716 will promote the PendingTasks to stable in v20. |
@Platonn i'm deeply sorry to have you wait for so long. Thank you very much for the detailed issue description. I will have a look this week into it |
yoyo @Platonn I actually could keep my promise. Please see the PR ;) |
Description
When the Server-Side-Rendered HTML is initially displayed in the browser, everything is visible.
And then CSR kicks in, and RxFor cuts long rendering task into smaller tasks (as intended).
But unfortunately Angular doesn't wait until all of DOM elements are rendered by RxFor and Angular already considers the hydration as done and destroys the Server-Side-Rendered DOM elements which were not yet rendered in CSR by RxFor. Therefore RxFor indirectly causes the DOM elements to be destroyed and recreated only later incrementally in separate tasks.
This might affect negatively CLS because the incrementally arriving components can cause layout shifts.
Steps to Reproduce the Issue
See the minimal app reproduction repo:
https://github.com/Platonn/test-rx-angular-non-destructive-hydration
For more, see screenshots
Initial SSR HTML displayed:
... and then CSR kicks in, Angular destroys the DOM and RxFor renders DOM elements incrementally in separate tasks:
For reference, I'm attaching also an exported Performance trace from Chrome Dev Tools:
Trace-20250402T144018.json
Environment
The text was updated successfully, but these errors were encountered: