New in Angular — afterNextRender and afterRender
A playful approach to exploring Angular’s new browser-only lifecycle hooks.
As the Angular team continues to work on framework improvements like fine-grained reactivity with Signals, and partial hydration with server-side rendering (SSR), they have introduced two new hooks. These hooks will be particularly useful when we need to update the DOM with our state, but only when running in the browser.
From the Angular docs:
Sometimes it’s necessary to use browser-only APIs to manually read or write the DOM. This can be challenging to do with the lifecycle events above, as they will also run during server-side rendering and pre-rendering. For this purpose, Angular provides afterRender and afterNextRender. These functions can be used unconditionally, but will only have an effect on the browser. Both functions accept a callback that will run after the next change detection cycle (including any nested cycles) has completed.
So, this means that we now have two methods that only run in the browser, making our updates to the DOM safe even when using SSR or pre-rendering.
afterNextRender
Perform one-time initialization, or observe a single, specific change to the DOM.
This event is triggered once after the next change detection cycle that is triggered by Angular. So that makes this event perfect for any initialization code that you need in your app, for example any third-party libraries, or browser-only APIs (for example initializing ResizeObserver API).
afterRender
Synchronize state with the DOM.
Any time there’s a change detection cycle, this event will be triggered and run. This is perfect to update the DOM every time Angular detects a change. You could use it to make additional writes to (or reads from) the DOM based on an app update.
Chase the blue dot!
Ok, we all know that reading the docs about a new feature is not the same as using it in an app, you’ll follow me while I showcase a small app (or should I say game?) that I built with Signals and afterNextRender and afterRender.
You can try the game here: https://after-render.netlify.app/ and review the code at GitHub https://github.com/eduardoRoth/after-render
The objective of this game is to move the red dot across the board until you touch the blue dot which (surprise!) moves to a different position
We use a HostListener to watch for the keydown event in the page and then move the red dot. If the updated coordinates of the red dot matches the ones of the blue dot, then we also update the position of it.
We use a WritableSignal<number> to store the score and update the DOM anytime it’s value is updated. The position of the red and blue dots is also stored in a WritableSignal<[number, number]> which represent the x and y coordinates of the board.
We have two methods to update the points and one to check if the red dot touched the blue dot:
movePoint handles updating the red dot position Signal with the new coordinates.
movePointToTouch handles updating the blue dot position Signal with the new coordinates.
hasTouchedPoint is a method to validate if red and blue dot position coordinates match, and then calls the method to move the blue dot.
So, we have the logic set up but, how can we update the DOM? By using afterRender!
As the signals are updated, they trigger a change detection cycle in Angular, which then triggers the afterRender event. We can benefit from this by calling the methods that draw the red and blue dot in the board each time a change has been processed:
We use afterNextRender to run an init board method, which just updates sightly the DOM. This is the perfect place if we wanted to modify our DOM once.
As you can see, the score is updated with Angular Change Detection through Signals fine-grained reactivity but, the position of the dots is handled by the afterRender event.
ExpressionChangedAfterItHasBeenCheckedError what?
If you try to update any variable in the afterRender event, you’ll get this error; so this event should only be used to make additional reads and writes to the DOM, not to update your state or anything else.
DOM updates made easier
So, by using afterRender we make sure the red and blue dots are updated in the DOM any time their position value updates.
There’s a lot of possibilities for our apps that afterRender and afterNextRender will open.
Remember that afterRender and afterNextRender are under development preview and their APIs are subject to change.