Skip to content
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

perf(core): Update LView consumer to only mark component for check #52302

Closed
wants to merge 1 commit into from

Conversation

atscott
Copy link
Contributor

@atscott atscott commented Oct 20, 2023

This commit updates the reactive template and host binding consumers to only mark their declaration components for refresh, but not parents/ancestors.

This also updates the AfterViewChecked hook to run when a component is refreshed during change detection but its host is not. It is reasonable to expect that the ngAfterViewChecked lifecycle hook will run when a signal updates and the component is refreshed. The hooks are typically run when the host is refreshed so without this change, the update to not mark ancestors dirty would have caused ngAfterViewChecked to not run.

resolves #14628
resolves #22646

resolves #34347 - this is not the direct request of the issue but generally forcing change detection to run is necessary only because a value was updated that needs to be synced to the DOM. Values that use signals will mark the component for check automatically so accessing the ChangeDetectorRef of a child is not necessary. The other part of this request was to avoid the need to "mark all views for checking since it wouldn't affect anything but itself". This is directly addressed by this PR - updating a signal that's read in the child view's template will not cause ancestors/"all views" to be refreshed.

@atscott atscott force-pushed the signalsPerComponentCd branch 3 times, most recently from 3f8ca6d to 18e3cc8 Compare October 20, 2023 21:07
@e-oz
Copy link

e-oz commented Oct 21, 2023

I am excited to see this, amazing news!

Just out of curiosity, as was asked in the first referenced issue: how can Angular know from which component change detection should start? Currently, it just starts from the root and that's how it finds all the onPush components, marked for check.

Could you please explain the new algorithm?

It is just out of curiosity - I’m happy to see this work.

@JeanMeche
Copy link
Member

JeanMeche commented Oct 21, 2023

@e-oz The answer lies in markAncestorsForTraversal, it stills starts from root but non-dirty components are skipped.

/**
* Ensures views above the given `lView` are traversed during change detection even when they are
* not dirty.
*
* This is done by setting the `HAS_CHILD_VIEWS_TO_REFRESH` flag up to the root, stopping when the
* flag is already `true` or the `lView` is detached.
*/
export function markAncestorsForTraversal(lView: LView) {

@e-oz
Copy link

e-oz commented Oct 21, 2023

Thanks a lot, @JeanMeche

@atscott atscott marked this pull request as ready for review October 26, 2023 20:37
@atscott atscott requested a review from alxhub October 26, 2023 20:46
@atscott atscott added target: rc This PR is targeted for the next release-candidate refactoring Issue that involves refactoring or code-cleanup area: core Issues related to the framework runtime core: change detection cross-cutting: signals labels Oct 26, 2023
@ngbot ngbot bot modified the milestone: Backlog Oct 26, 2023
@atscott atscott force-pushed the signalsPerComponentCd branch 3 times, most recently from 91dbfc0 to f9c8ba7 Compare October 27, 2023 16:04
@atscott atscott force-pushed the signalsPerComponentCd branch 3 times, most recently from 53dd70d to c9effb3 Compare October 30, 2023 19:14
This commit updates the reactive template and host binding consumers to
only mark their declaration components for refresh, but not parents/ancestors.

This also updates the `AfterViewChecked` hook to run when a component is
refreshed during change detection but its host is not. It is reasonable
to expect that the `ngAfterViewChecked` lifecycle hook will run when a
signal updates and the component is refreshed. The hooks are typically
run when the host is refreshed so without this change, the update to
not mark ancestors dirty would have caused `ngAfterViewChecked` to not
run.

resolves angular#14628
resolves angular#22646

resolves angular#34347 - this is not the direct request of the issue but
generally forcing change detection to run is necessary only because a
value was updated that needs to be synced to the DOM. Values that use
signals will mark the component for check automatically so accessing the
`ChangeDetectorRef` of a child is not necessary. The other part of this
request was to avoid the need to "mark all views for checking since
it wouldn't affect anything but itself". This is directly addressed by
this commit - updating a signal that's read in the view's template
will not cause ancestors/"all views" to be refreshed.
@atscott atscott added the action: merge The PR is ready for merge by the caretaker label Oct 31, 2023
@alxhub
Copy link
Member

alxhub commented Oct 31, 2023

This PR was merged into the repository by commit ac2d0c6.

@alxhub alxhub closed this in ac2d0c6 Oct 31, 2023
alxhub pushed a commit that referenced this pull request Oct 31, 2023
…52302)

This commit updates the reactive template and host binding consumers to
only mark their declaration components for refresh, but not parents/ancestors.

This also updates the `AfterViewChecked` hook to run when a component is
refreshed during change detection but its host is not. It is reasonable
to expect that the `ngAfterViewChecked` lifecycle hook will run when a
signal updates and the component is refreshed. The hooks are typically
run when the host is refreshed so without this change, the update to
not mark ancestors dirty would have caused `ngAfterViewChecked` to not
run.

resolves #14628
resolves #22646

resolves #34347 - this is not the direct request of the issue but
generally forcing change detection to run is necessary only because a
value was updated that needs to be synced to the DOM. Values that use
signals will mark the component for check automatically so accessing the
`ChangeDetectorRef` of a child is not necessary. The other part of this
request was to avoid the need to "mark all views for checking since
it wouldn't affect anything but itself". This is directly addressed by
this commit - updating a signal that's read in the view's template
will not cause ancestors/"all views" to be refreshed.

PR Close #52302
atscott added a commit to atscott/angular that referenced this pull request Oct 31, 2023
…tion

The significance of the combination of angular#51854 and angular#52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes angular#50320
atscott added a commit to atscott/angular that referenced this pull request Oct 31, 2023
…tion

The significance of the combination of angular#51854 and angular#52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes angular#50320
atscott added a commit to atscott/angular that referenced this pull request Oct 31, 2023
…tion

The significance of the combination of angular#51854 and angular#52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes angular#50320
atscott added a commit to atscott/angular that referenced this pull request Oct 31, 2023
…tion

The significance of the combination of angular#51854 and angular#52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes angular#50320
atscott added a commit to atscott/angular that referenced this pull request Nov 2, 2023
…tion

The significance of the combination of angular#51854 and angular#52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes angular#50320
alxhub pushed a commit that referenced this pull request Nov 2, 2023
…tion (#52476)

The significance of the combination of #51854 and #52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes #50320

PR Close #52476
alxhub pushed a commit that referenced this pull request Nov 2, 2023
…tion (#52476)

The significance of the combination of #51854 and #52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes #50320

PR Close #52476
Abseil-byte pushed a commit to Abseil-byte/angular that referenced this pull request Nov 5, 2023
…tion (angular#52476)

The significance of the combination of angular#51854 and angular#52302 went mostly
unnoticed. The first removed a unidirectional data flow constraint for
transplanted views and the second updated the signal implementation to
share transplanted view logic. The result is that we automatically get behavior
that (mostly) removes `ExpressionChangedAfterItWasCheckedError` when signals are
used to drive application state to DOM synchronization.

fixes angular#50320

PR Close angular#52476
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Dec 1, 2023
tbondwilkinson pushed a commit to tbondwilkinson/angular that referenced this pull request Dec 6, 2023
…ngular#52302)

This commit updates the reactive template and host binding consumers to
only mark their declaration components for refresh, but not parents/ancestors.

This also updates the `AfterViewChecked` hook to run when a component is
refreshed during change detection but its host is not. It is reasonable
to expect that the `ngAfterViewChecked` lifecycle hook will run when a
signal updates and the component is refreshed. The hooks are typically
run when the host is refreshed so without this change, the update to
not mark ancestors dirty would have caused `ngAfterViewChecked` to not
run.

resolves angular#14628
resolves angular#22646

resolves angular#34347 - this is not the direct request of the issue but
generally forcing change detection to run is necessary only because a
value was updated that needs to be synced to the DOM. Values that use
signals will mark the component for check automatically so accessing the
`ChangeDetectorRef` of a child is not necessary. The other part of this
request was to avoid the need to "mark all views for checking since
it wouldn't affect anything but itself". This is directly addressed by
this commit - updating a signal that's read in the view's template
will not cause ancestors/"all views" to be refreshed.

PR Close angular#52302
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
…ngular#52302)

This commit updates the reactive template and host binding consumers to
only mark their declaration components for refresh, but not parents/ancestors.

This also updates the `AfterViewChecked` hook to run when a component is
refreshed during change detection but its host is not. It is reasonable
to expect that the `ngAfterViewChecked` lifecycle hook will run when a
signal updates and the component is refreshed. The hooks are typically
run when the host is refreshed so without this change, the update to
not mark ancestors dirty would have caused `ngAfterViewChecked` to not
run.

resolves angular#14628
resolves angular#22646

resolves angular#34347 - this is not the direct request of the issue but
generally forcing change detection to run is necessary only because a
value was updated that needs to be synced to the DOM. Values that use
signals will mark the component for check automatically so accessing the
`ChangeDetectorRef` of a child is not necessary. The other part of this
request was to avoid the need to "mark all views for checking since
it wouldn't affect anything but itself". This is directly addressed by
this commit - updating a signal that's read in the view's template
will not cause ancestors/"all views" to be refreshed.

PR Close angular#52302
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: core Issues related to the framework runtime core: change detection cross-cutting: signals refactoring Issue that involves refactoring or code-cleanup target: rc This PR is targeted for the next release-candidate
Projects
None yet
5 participants