-
Notifications
You must be signed in to change notification settings - Fork 26.5k
fix(core): effects wait for ngOnInit for their first run #52473
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
Conversation
95442f4
to
1f1ad34
Compare
d0e9663
to
befa229
Compare
befa229
to
1a81762
Compare
When an effect is created in a component constructor, it might read signals which are derived from component inputs. These signals may be unreliable or (in the case of the proposed input signals) may throw if accessed before the component is first change detected (which is what makes required inputs available). Depending on the scenario involved, the effect may or may not run before this initialization takes place, which isn't a great developer experience. In particular, effects created during CD (e.g. via control flow) work fine, as do effects created in bootstrap thanks to the sync CD it performs. When an effect is created through dynamic component creation outside of CD though (such as on router navigations), it runs before the component is first CD'd, causing the issue. In fact, in the signal components RFC we described how effects would wait until ngOnInit for their first execution for exactly this reason, but this behavior was never implemented as it was thought our effect scheduling design made it unnecessary. This is true of the regular execution of effects but the above scenario shows that *creation* of the effect is still vulnerable. Thus, this logic is needed. This commit makes effects sensitive to their creation context, by injecting `ChangeDetectorRef` optionally. An effect created with an injector that's tied to a component will wait until that component is initialized before initially being scheduled. TestBed effect flushing is also adjusted to account for the additional interaction with change detection.
1a81762
to
91ea7db
Compare
This PR was merged into the repository by commit ee9605f. |
When an effect is created in a component constructor, it might read signals which are derived from component inputs. These signals may be unreliable or (in the case of the proposed input signals) may throw if accessed before the component is first change detected (which is what makes required inputs available). Depending on the scenario involved, the effect may or may not run before this initialization takes place, which isn't a great developer experience. In particular, effects created during CD (e.g. via control flow) work fine, as do effects created in bootstrap thanks to the sync CD it performs. When an effect is created through dynamic component creation outside of CD though (such as on router navigations), it runs before the component is first CD'd, causing the issue. In fact, in the signal components RFC we described how effects would wait until ngOnInit for their first execution for exactly this reason, but this behavior was never implemented as it was thought our effect scheduling design made it unnecessary. This is true of the regular execution of effects but the above scenario shows that *creation* of the effect is still vulnerable. Thus, this logic is needed. This commit makes effects sensitive to their creation context, by injecting `ChangeDetectorRef` optionally. An effect created with an injector that's tied to a component will wait until that component is initialized before initially being scheduled. TestBed effect flushing is also adjusted to account for the additional interaction with change detection. PR Close #52473
@alxhub Is there a tracking issue for this and other related developer preview features? The specific concern I have is related to Here's an oversimplified example where this may cause unexpected behavior.
Maybe |
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. |
When an effect is created in a component constructor, it might read signals which are derived from component inputs. These signals may be unreliable or (in the case of the proposed input signals) may throw if accessed before the component is first change detected (which is what makes required inputs available). Depending on the scenario involved, the effect may or may not run before this initialization takes place, which isn't a great developer experience. In particular, effects created during CD (e.g. via control flow) work fine, as do effects created in bootstrap thanks to the sync CD it performs. When an effect is created through dynamic component creation outside of CD though (such as on router navigations), it runs before the component is first CD'd, causing the issue. In fact, in the signal components RFC we described how effects would wait until ngOnInit for their first execution for exactly this reason, but this behavior was never implemented as it was thought our effect scheduling design made it unnecessary. This is true of the regular execution of effects but the above scenario shows that *creation* of the effect is still vulnerable. Thus, this logic is needed. This commit makes effects sensitive to their creation context, by injecting `ChangeDetectorRef` optionally. An effect created with an injector that's tied to a component will wait until that component is initialized before initially being scheduled. TestBed effect flushing is also adjusted to account for the additional interaction with change detection. PR Close angular#52473
When an effect is created in a component constructor, it might read signals which are derived from component inputs. These signals may be unreliable or (in the case of the proposed input signals) may throw if accessed before the component is first change detected (which is what makes required inputs available).
Depending on the scenario involved, the effect may or may not run before this initialization takes place, which isn't a great developer experience. In particular, effects created during CD (e.g. via control flow) work fine, as do effects created in bootstrap thanks to the sync CD it performs. When an effect is created through dynamic component creation outside of CD though (such as on router navigations), it runs before the component is first CD'd, causing the issue.
In fact, in the signal components RFC we described how effects would wait until ngOnInit for their first execution for exactly this reason, but this behavior was never implemented as it was thought our effect scheduling design made it unnecessary. This is true of the regular execution of effects but the above scenario shows that creation of the effect is still vulnerable. Thus, this logic is needed.
This commit makes effects sensitive to their creation context, by injecting
ChangeDetectorRef
optionally. An effect created with an injector that's tied to a component will wait until that component is initialized before initially being scheduled. TestBed effect flushing is also adjusted to account for the additional interaction with change detection.