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

Reactivity: effects won't execute if created in a component that is detached from a change detection tree #55808

Open
pkozlowski-opensource opened this issue May 15, 2024 · 1 comment · May be fixed by #56501
Labels
area: core Issues related to the framework runtime core: change detection core: reactivity Work related to fine-grained reactivity in the core framework cross-cutting: signals
Milestone

Comments

@pkozlowski-opensource
Copy link
Member

Which @angular/* package(s) are the source of the bug?

core

Is this a regression?

No

Description

Effects won't execute if created in a component that is detached from a change detection tree, example:

export class CDDetatched {
  constructor(cdRef: ChangeDetectorRef) {
    cdRef.detach();
  }

  e = effect(() => console.log('An effect in a detached component'));
}

Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/stackblitz-starters-7zd1fv?file=src%2Fmain.tsFmain.ts

Please provide the exception or error you saw

No response

Please provide the environment you discovered this bug in (run ng version)

No response

Anything else?

Created from #55644

@pkozlowski-opensource pkozlowski-opensource added area: core Issues related to the framework runtime core: change detection core: reactivity Work related to fine-grained reactivity in the core framework cross-cutting: signals labels May 15, 2024
@ngbot ngbot bot added this to the needsTriage milestone May 15, 2024
@pkozlowski-opensource
Copy link
Member Author

This bugs is surfaced due to the implementation choice described in #55311 (comment)

alxhub added a commit to alxhub/angular that referenced this issue Jun 18, 2024
The original effect design for Angular had one "bucket" of effects, which
are scheduled on the microtask queue. This approach got us pretty far, but
as developers have built more complex reactive systems, we've hit the
limitations of this design.

This commit changes the nature of effects significantly. In particular,
effects created in components have a completely new scheduling system, which
executes them as a part of the change detection cycle. This results in
behavior similar to that of nested effects in other reactive frameworks. The
scheduling behavior here uses the "mark for traversal" flag
(`HasChildViewsToRefresh`). This has really nice behavior:

 * if the component is dirty already, effects run following preorder hooks
   (ngOnInit, etc).
 * if the component isn't dirty, it doesn't get change detected only because
   of the dirty effect.

This is not a breaking change, since `effect()` is in developer preview (and
it remains so).

Fixes angular#55311
Fixes angular#55808
Fixes angular#55644
@alxhub alxhub linked a pull request Jun 18, 2024 that will close this issue
alxhub added a commit to alxhub/angular that referenced this issue Jul 9, 2024
The original effect design for Angular had one "bucket" of effects, which
are scheduled on the microtask queue. This approach got us pretty far, but
as developers have built more complex reactive systems, we've hit the
limitations of this design.

This commit changes the nature of effects significantly. In particular,
effects created in components have a completely new scheduling system, which
executes them as a part of the change detection cycle. This results in
behavior similar to that of nested effects in other reactive frameworks. The
scheduling behavior here uses the "mark for traversal" flag
(`HasChildViewsToRefresh`). This has really nice behavior:

 * if the component is dirty already, effects run following preorder hooks
   (ngOnInit, etc).
 * if the component isn't dirty, it doesn't get change detected only because
   of the dirty effect.

This is not a breaking change, since `effect()` is in developer preview (and
it remains so).

As a part of this redesigned `effect()` behavior, the `allowSignalWrites`
flag was removed. Effects no longer prohibit writing to signals at all. This
decision was taken in response to feedback / observations of usage patterns,
which showed the benefit of the restriction did not justify the DX cost.

Fixes angular#55311
Fixes angular#55808
Fixes angular#55644
Fixes angular#56863
alxhub added a commit to alxhub/angular that referenced this issue Jul 9, 2024
The original effect design for Angular had one "bucket" of effects, which
are scheduled on the microtask queue. This approach got us pretty far, but
as developers have built more complex reactive systems, we've hit the
limitations of this design.

This commit changes the nature of effects significantly. In particular,
effects created in components have a completely new scheduling system, which
executes them as a part of the change detection cycle. This results in
behavior similar to that of nested effects in other reactive frameworks. The
scheduling behavior here uses the "mark for traversal" flag
(`HasChildViewsToRefresh`). This has really nice behavior:

 * if the component is dirty already, effects run following preorder hooks
   (ngOnInit, etc).
 * if the component isn't dirty, it doesn't get change detected only because
   of the dirty effect.

This is not a breaking change, since `effect()` is in developer preview (and
it remains so).

As a part of this redesigned `effect()` behavior, the `allowSignalWrites`
flag was removed. Effects no longer prohibit writing to signals at all. This
decision was taken in response to feedback / observations of usage patterns,
which showed the benefit of the restriction did not justify the DX cost.

Fixes angular#55311
Fixes angular#55808
Fixes angular#55644
Fixes angular#56863
alxhub added a commit to alxhub/angular that referenced this issue Jul 12, 2024
The original effect design for Angular had one "bucket" of effects, which
are scheduled on the microtask queue. This approach got us pretty far, but
as developers have built more complex reactive systems, we've hit the
limitations of this design.

This commit changes the nature of effects significantly. In particular,
effects created in components have a completely new scheduling system, which
executes them as a part of the change detection cycle. This results in
behavior similar to that of nested effects in other reactive frameworks. The
scheduling behavior here uses the "mark for traversal" flag
(`HasChildViewsToRefresh`). This has really nice behavior:

 * if the component is dirty already, effects run following preorder hooks
   (ngOnInit, etc).
 * if the component isn't dirty, it doesn't get change detected only because
   of the dirty effect.

This is not a breaking change, since `effect()` is in developer preview (and
it remains so).

As a part of this redesigned `effect()` behavior, the `allowSignalWrites`
flag was removed. Effects no longer prohibit writing to signals at all. This
decision was taken in response to feedback / observations of usage patterns,
which showed the benefit of the restriction did not justify the DX cost.

Fixes angular#55311
Fixes angular#55808
Fixes angular#55644
Fixes angular#56863
alxhub added a commit to alxhub/angular that referenced this issue Jul 17, 2024
The original effect design for Angular had one "bucket" of effects, which
are scheduled on the microtask queue. This approach got us pretty far, but
as developers have built more complex reactive systems, we've hit the
limitations of this design.

This commit changes the nature of effects significantly. In particular,
effects created in components have a completely new scheduling system, which
executes them as a part of the change detection cycle. This results in
behavior similar to that of nested effects in other reactive frameworks. The
scheduling behavior here uses the "mark for traversal" flag
(`HasChildViewsToRefresh`). This has really nice behavior:

 * if the component is dirty already, effects run following preorder hooks
   (ngOnInit, etc).
 * if the component isn't dirty, it doesn't get change detected only because
   of the dirty effect.

This is not a breaking change, since `effect()` is in developer preview (and
it remains so).

As a part of this redesigned `effect()` behavior, the `allowSignalWrites`
flag was removed. Effects no longer prohibit writing to signals at all. This
decision was taken in response to feedback / observations of usage patterns,
which showed the benefit of the restriction did not justify the DX cost.

Fixes angular#55311
Fixes angular#55808
Fixes angular#55644
Fixes angular#56863
alxhub added a commit to alxhub/angular that referenced this issue Jul 17, 2024
The original effect design for Angular had one "bucket" of effects, which
are scheduled on the microtask queue. This approach got us pretty far, but
as developers have built more complex reactive systems, we've hit the
limitations of this design.

This commit changes the nature of effects significantly. In particular,
effects created in components have a completely new scheduling system, which
executes them as a part of the change detection cycle. This results in
behavior similar to that of nested effects in other reactive frameworks. The
scheduling behavior here uses the "mark for traversal" flag
(`HasChildViewsToRefresh`). This has really nice behavior:

 * if the component is dirty already, effects run following preorder hooks
   (ngOnInit, etc).
 * if the component isn't dirty, it doesn't get change detected only because
   of the dirty effect.

This is not a breaking change, since `effect()` is in developer preview (and
it remains so).

As a part of this redesigned `effect()` behavior, the `allowSignalWrites`
flag was removed. Effects no longer prohibit writing to signals at all. This
decision was taken in response to feedback / observations of usage patterns,
which showed the benefit of the restriction did not justify the DX cost.

Fixes angular#55311
Fixes angular#55808
Fixes angular#55644
Fixes angular#56863
alxhub added a commit to alxhub/angular that referenced this issue Jul 17, 2024
The original effect design for Angular had one "bucket" of effects, which
are scheduled on the microtask queue. This approach got us pretty far, but
as developers have built more complex reactive systems, we've hit the
limitations of this design.

This commit changes the nature of effects significantly. In particular,
effects created in components have a completely new scheduling system, which
executes them as a part of the change detection cycle. This results in
behavior similar to that of nested effects in other reactive frameworks. The
scheduling behavior here uses the "mark for traversal" flag
(`HasChildViewsToRefresh`). This has really nice behavior:

 * if the component is dirty already, effects run following preorder hooks
   (ngOnInit, etc).
 * if the component isn't dirty, it doesn't get change detected only because
   of the dirty effect.

This is not a breaking change, since `effect()` is in developer preview (and
it remains so).

As a part of this redesigned `effect()` behavior, the `allowSignalWrites`
flag was removed. Effects no longer prohibit writing to signals at all. This
decision was taken in response to feedback / observations of usage patterns,
which showed the benefit of the restriction did not justify the DX cost.

Fixes angular#55311
Fixes angular#55808
Fixes angular#55644
Fixes angular#56863
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: core Issues related to the framework runtime core: change detection core: reactivity Work related to fine-grained reactivity in the core framework cross-cutting: signals
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant