Fine-Grained Reactivity with Signals: A New Frontier in Front-End Frameworks
TL;DR:
This blog is based on my session, "Fine-Grained Reactivity with Signals: A New Frontier in Front-End Frameworks," presented on April 5, 2025, at Orlando Code Camp 2025. You can watch a recorded overview—featuring both the presentation and live code demos—on YouTube. It’s presented in podcast form and was produced with the help of Notebook LM powered by Gemini AI: Watch the overview.
What Are Signals?
A signal is a reactive state container that represents a value over time. When that value changes, any dependent code is automatically re-executed. Think of a signal like a live variable—one that keeps your UI or logic in sync without requiring manual subscriptions or external tools.
Key characteristics:
- Synchronous: updates happen immediately.
- Auto-tracked: dependencies are tracked implicitly.
- Minimalistic: no need for explicit subscription management.
For example, if you’re familiar with React, signals combine aspects of
useState()
and useEffect()
but without the
boilerplate. For RxJS users, signals are closer
to BehaviorSubject
, but designed specifically for local
UI state and synchronous flows.
Why Signals? Why Now?
Having worked in support, QA, and now as a software engineer at Design Interactive, I've seen many patterns come and go. Signals stand out due to their simplicity and performance. Unlike traditional observable models or hook-based reactivity, signals:
- Track dependencies automatically.
- Run synchronously within the same execution tick.
- Eliminate the need for dependency arrays or manual subscription cleanup.
This makes them an ideal fit for front-end apps where performance, clarity, and reactivity matter.
A Brief History of Signals
Although signals may seem new, they’re grounded in decades of reactive programming concepts. The foundation traces back to the 1960s, with ideas like dataflow and spreadsheets—where a change in one cell automatically updates others.
In 2010, Knockout.js introduced observables and auto-updating UIs to JavaScript. MobX built on these ideas with transparent functional reactive programming.
By 2017, frameworks like SolidJS popularized the term
"signal," explicitly using it to deliver fine-grained updates.
Vue 3 followed with its Composition API and ref()
,
which behaves similarly. Angular and Svelte later adopted
signals and signal-like patterns (such as "runes") in 2023–2024.
Today, signals are emerging as a unifying reactive pattern across frameworks.
Signals: The Core Concepts
Every modern reactive JavaScript framework relies on three core building blocks:
-
Observable State (signal) – Also known as atoms or refs, these
store reactive values and notify dependents.
-
Computed Values (computed) – Also called derivations or memos,
these represent values derived from signals.
- Side Effects (effect) – Also referred to as watchers or reactions, these execute when signal values change, typically to update the DOM or trigger other behaviors.
Frameworks like Angular (signals), Vue (refs), Svelte ($:
),
and React (hooks) revolve around these principles.
Signals forms a dependency graph. When a signal changes, only its dependents are notified, resulting in optimized and predictable updates.
Building a Basic Signals System
Want to understand how signals work internally? I created a Basic Implementation in JavaScript on GitHub to illustrate the concept.
This simple snippet shows how to create a signal, update it, and react to changes:
const count = signal(0);
// Read value
console.log(count.get());
// Update value
count.set(1);
// React to changes
effect(() => {
console.log('Count is now:', count.get());
});
This design demonstrates the essence of fine-grained reactivity: state + effects, with automatic tracking and synchronous execution.
Angular Signals in Action
Imagine a .NET 7 backend feeding an Angular front end with 30 components. Without signals, clicking a single button might trigger re-checks across the entire component tree. With signals, only the affected parts update. That means better performance, fewer rendering bugs, and a smoother dev experience.
When to Use Signals vs. RxJS
- Use signals for UI state and synchronous logic within components.
-
Use RxJS (e.g.
BehaviorSubject
,Observable
) for event streams, async data, or app-wide state sharing.
Signals offer a concise, component-scoped syntax for local state. RxJS remains best for async streams, HTTP observables, and cross-component workflows.
Angular adopted signals in version 16+ to reduce reliance on
Zone.js
for change detection.
Historically, Angular’s reactivity was coarse-grained—a change in one part could trigger detection across many unrelated components. While Angular used zones, React has its own challenge with Virtual DOM diffing, which can also lead to broad re-renders.
With Angular Signals, reactivity becomes fine-grained. Updates are limited to only the parts of the UI that actually use the changed signal.
Explore this behavior yourself in my Angular Rendering Demo on GitHub, which showcases:
- Coarse-grained change detection using
ngDoCheck
-
Fine-grained reactivity using
signal()
andeffect()
- Manual two-way binding with signals
The Future of Signals
Signals are becoming the go-to standard for UI reactivity across frameworks. As the ecosystem matures, we’re seeing growing alignment around this pattern.
More importantly, there’s an official TC39 proposal to introduce signals as a JavaScript language primitive. While still in early stages, this could lead to native browser support and reduced reliance on libraries.
Signals aren’t just another reactive flavor—they may become a core primitive in the future of front-end development.
Best Practices for Working with Signals
- Scope signals to local UI state when possible.
- Use
computed()
for derived values.
- Don’t use
computed
for side effects—useeffect()
.
- Avoid mutating signal values directly; use
.set()
or.update()
.
Resources
Let’s Connect
I’m always happy to chat about front-end architecture or help others get started with modern reactivity:
"Make it work, make it right, make it fast." – Kent Beck, an American software engineer and the creator of Extreme Programming
Stay curious. Keep learning. And keep building! ¡Hasta la próxima!
– Javi (Software Engineer & GDG Community Organizer)
Comments
Post a Comment