Fine-Grained Reactivity with Signals: A New Frontier in Front-End Frameworks

Signals 

TL;DR:

Signals are transforming how modern JavaScript frameworks manage state and UI updates. This blog introduces the foundational concepts of signals, explores their history, and shows how they’re being adopted by frameworks like Angular, Vue, and SolidJS. You'll also get a practical glimpse into how signals work under the hood and how Angular leverages them for fine-grained reactivity.

By Javi, Developer and Community Organizer at GDG Central Florida

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:

  1. Observable State (signal) – Also known as atoms or refs, these store reactive values and notify dependents.

  2. Computed Values (computed) – Also called derivations or memos, these represent values derived from signals.

  3. 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() and effect()
  • 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—use effect().
  • 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

Popular posts from this blog

Prompt Engineering & Frameworks: A Practical Guide

Celebrating Innovation and Empowerment: A Recap of International Women's Day 2024 - Impact the Future

Winners from Google IoExtended Hackathon 2023 in Florida