Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(core): change effect() execution timing & no-op allowSignalWrites #57874

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

Closed
wants to merge 1 commit into from

Conversation

alxhub
Copy link
Member

@alxhub alxhub commented Sep 18, 2024

This commit flips the flag that was added in 4e890cc, putting the new effect timing into... effect :)

BREAKING CHANGE:

Generally this PR has two implications:

  • effects which are triggered outside of change detection run as part of
    the change detection process instead of as a microtask. Depending on the
    specifics of application/test setup, this can result in them executing
    earlier or later (or requiring additional test steps to trigger; see below
    examples).

  • effects which are triggered during change detection (e.g. by input signals) run earlier, before the component's template.

We've seen a few common failure cases:

  • Tests which used to rely on the Promise timing of effects now need to await whenStable() or call .detectChanges() in order for effects to run.

  • Tests which use faked clocks may need to fast-forward/flush the clock to cause effects to run.

  • effect()s triggered during CD could rely on the application being fully rendered (for example, they could easily read computed styles, etc). With the change, they run before the component's updates and can get incorrect answers. The recent afterRenderEffect() API is a natural replacement for this style of effect.

  • effect()s which synchronize with the forms system are particularly timing-sensitive and might need to adjust their initialization timing.

Fixes #55311
Fixes #55808
Fixes #55644
Fixes #56863

@angular-robot angular-robot bot added detected: breaking change PR contains a commit with a breaking change detected: feature PR contains a feature commit area: core Issues related to the framework runtime labels Sep 18, 2024
@ngbot ngbot bot added this to the Backlog milestone Sep 18, 2024
@e-oz
Copy link

e-oz commented Sep 19, 2024

Nice change!
Will it affect viewChild()?

@e-oz
Copy link

e-oz commented Sep 19, 2024

Let me explain my comment a bit. I’ve got a cold, so my brain is working at 50% of its capacity. Please excuse me if I post nonsense.

Important

I would never write this code. It is not about my existing code.

Code example:

class ExampleComponent {
    child = viewChild<ElementRef>('child');

    _ = effect(() => {
       const child = this.child();
       if (child) {
         // Here user expects that `child` already has `nativeElement`, because `child` is not undefined
         child.nativeElement.color = 'green';
       }
    });
}

If I misunderstood something and the child will be colored green, please just disregard my comment.

@atscott
Copy link
Contributor

atscott commented Sep 19, 2024

@e-oz that code is totally fine because the query is reactive. The effect may run twice now as opposed to once prior to the change, depending on whether the result is available during creation mode.

It would be a problem if that query was using the old @ViewChild without static: true because the effect would run before the query result is available (in this case, the effect would likely be based on some other signal like an input).

@alxhub alxhub added the target: major This PR is targeted for the next major release label Sep 19, 2024
@alxhub
Copy link
Member Author

alxhub commented Sep 19, 2024

@e-oz yep, that should be fine, but this is also a great use case for afterRenderEffect which guarantees DOM rendering is complete.

@alxhub alxhub added the merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note label Sep 19, 2024
@alxhub
Copy link
Member Author

alxhub commented Sep 19, 2024

Caretaker: this will require cl/676508958 submitted prior to merge (ok to merge the patch in advance). With that patch, this change is a no-op in g3 and does not need a presubmit.

Copy link
Contributor

@atscott atscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM other than the timing note I mentioned in chat

This commit flips the flag that was added in 4e890cc, putting the new effect
timing into... effect :)

BREAKING CHANGE:

Generally this PR has two implications:

* effects which are triggered outside of change detection run as part of
  the change detection process instead of as a microtask. Depending on the
  specifics of application/test setup, this can result in them executing
  earlier or later (or requiring additional test steps to trigger; see below
  examples).

* effects which are triggered during change detection (e.g. by input
  signals) run _earlier_, before the component's template.

We've seen a few common failure cases:

* Tests which used to rely on the `Promise` timing of effects now need to
  `await whenStable()` or call `.detectChanges()` in order for effects to
  run.

* Tests which use faked clocks may need to fast-forward/flush the clock to
  cause effects to run.

* `effect()`s triggered during CD could rely on the application being fully
  rendered (for example, they could easily read computed styles, etc). With
  the change, they run before the component's updates and can get incorrect
  answers. The recent `afterRenderEffect()` API is a natural replacement for
  this style of effect.

* `effect()`s which synchronize with the forms system are particularly
  timing-sensitive and might need to adjust their initialization timing.

Fixes angular#55311
Fixes angular#55808
Fixes angular#55644
Fixes angular#56863
@angular-robot angular-robot bot added area: core Issues related to the framework runtime and removed area: core Issues related to the framework runtime labels Sep 19, 2024
@ngbot ngbot bot modified the milestone: Backlog Sep 19, 2024
@alxhub alxhub added the action: merge The PR is ready for merge by the caretaker label Sep 19, 2024
@atscott
Copy link
Contributor

atscott commented Sep 19, 2024

This PR was merged into the repository by commit fc59e2a.

The changes were merged into the following branches: main

@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 Oct 20, 2024
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 detected: breaking change PR contains a commit with a breaking change detected: feature PR contains a feature commit merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note target: major This PR is targeted for the next major release
Projects
None yet
3 participants