feat(core): introduce afterRenderEffect#57549
Conversation
|
Deployed adev-preview for 59e169c to: https://ng-dev-previews-fw--pr-angular-angular-57549-adev-prev-oyzoua3t.web.app Note: As new commits are pushed to this pull request, this link is updated after the preview is rebuilt. |
|
I love this change, but since the signalification of the primitive values returned by each phase callback is abstracted away from us, this seems to be a bad fit for use cases that require multiple values to be passed from one phase to another. For example: afterRenderEffect({
earlyRead: () => {
const element = this.someElementRef.nativeElement;
return [element.offsetLeft, element.offsetTop];
},
write: ([x, y]) => animateThing(x, y)
})In this example, I assume that the write phase would run on every render because the earlyRead phase returns a new array each time. Is that correct? The workaround I use today isn't very ergonomic: position = signal<[number,number]>([0,0], {equal: arrayDeepEqual});
afterRender({
earlyRead: () => {
const element = this.someElementRef().nativeElement;
this.position.set([element.offsetLeft, element.offsetTop]);
}
});
// only run the write phase when this.position changes, after accounting for custom equality fn
effect(() => {
const [x, y] = this.position();
afterNextRender({ write: () => animateThing(x, y) });
});It seems to work, but it feels brittle. What do you think? |
There was a problem hiding this comment.
Does this mean that if one cleanup function errors, the others don't run but are still cleared?
Should this be more like
for ... {
try {
cleanupFn();
} finally {
this.cleanup?.delete(cleanupFn);
}
}
There was a problem hiding this comment.
I thought about this before, and chose (for no strong reason other than intuition) to implement a mental model where we considered all the registered cleanup functions to be a part of the same logical operation. We really need to standardize this model (effect() for example overwrites the previous cleanup function when a new one is registered).
|
LGTM overall but adding a cleanup label since:
|
4c72cab to
4f34cef
Compare
Yeah, we saw this too, but I don't know if there is an API that's ideal here. There seem to be two potential design avenues which address the problem:
Both of these solutions have their downsides. With equality functions, you have to remember to pass them. With more granular return objects, the signal wrapping only works at one layer - if I get creative and |
4f34cef to
4eee890
Compare
Implement the `afterRenderEffect` primitive, which creates effect(s) that run as part of Angular's `afterRender` sequence. `afterRenderEffect` is a useful primitive for expressing DOM operations in a declarative, reactive way. The API itself mirrors `afterRender` and `afterNextRender` with one big difference: values are propagated from phase to phase as signals instead of as plain values. As a result, later phases may not need to execute if the values returned by earlier phases do not change.
4eee890 to
59e169c
Compare
|
@alxhub the |
thePunderWoman
left a comment
There was a problem hiding this comment.
reviewed-for: public-api
AndrewKushnir
left a comment
There was a problem hiding this comment.
Reviewed-for: public-api
AndrewKushnir
left a comment
There was a problem hiding this comment.
Reviewed-for: size-tracking
|
This PR was merged into the repository by commit be2e496. The changes were merged into the following branches: main |
|
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Implement the
afterRenderEffectprimitive, which creates effect(s) that run as part of Angular'safterRendersequence.afterRenderEffectis a useful primitive for expressing DOM operations in a declarative, reactive way.The API itself mirrors
afterRenderandafterNextRenderwith one big difference: values are propagated from phase to phase as signals instead of as plain values. As a result, later phases may not need to execute if the values returned by earlier phases do not change.