
Angular Signals, Reactive Context, and Dynamic Dependency Tracking

๐ Abstract
The article discusses the concept of "reactive context" and dependency tracking in Angular Signals, and how to avoid related bugs.
๐ Q&A
[01] Dependency Tracking
1. What is the "dependency graph" in Angular Signals?
- The dependency graph is a graph of nodes, where each node implements the ReactiveNode interface.
- Producers are nodes that contain values and notify about new values.
- Consumers are nodes that read produced values.
- Signals are producers, computed() is both producer and consumer, effect() is a consumer, and templates are consumers.
2. How does automatic dependency tracking work in Angular Signals?
- There is a global variable called activeConsumer.
- When computed(), effect(), or a template is being executed:
- They read the value of activeConsumer to remember the previous consumer.
- They register themselves as the activeConsumer.
- They run their function or execute the template (potentially reading some signals).
- They register the previous consumer (from step 1) as the activeConsumer.
- When a producer is read, it retrieves the value of activeConsumer and includes this active consumer in the list of consumers dependent on the signal.
- When a signal is updated, it sends a notification to every consumer from its list.
3. What is the importance of understanding dependency tracking in Angular Signals?
- Consumers (computed(), effect(), templates) don't need to worry about adding the signals they read to the list of dependencies. Signals will do it themselves using the activeConsumer variable.
- This means that no matter how deep in the function call chain a signal is read, it will be added to the list of dependencies.
- Understanding this behavior is important to avoid bugs related to unintended dependencies or lack of dependencies.
[02] Reactive Context
1. What is the "reactive context" in Angular Signals?
- The reactive context is related to the activeConsumer variable.
- When activeConsumer is not null, signals that are read will add the activeConsumer to the list of consumers.
- If a reactive node is read while activeConsumer is empty, it will not create any new link in the reactive nodes dependency graph.
2. How can the reactive context be unintentionally leaked?
- Leaking the reactive context can happen in various ways, such as:
- Creating an instance of a class that reads some signals.
- Calling a function that calls another function, which reads a signal.
- Emitting a new value to an observable.
- This can lead to unexpected behavior, where signals that should not be dependencies end up triggering recomputations.
3. How can the use of untracked() help manage the reactive context?
- untracked() can be used to control which dependencies are tracked by a computed() or effect().
- If you don't want a function called within a computed() or effect() to trigger a recomputation when its value changes, you can wrap it with untracked().
- This helps prevent unintended dependencies and leaks in the reactive context.
Shared by Daniel Chen ยท
ยฉ 2024 NewMotor Inc.