Back to blog

Signals: The Reactivity Standard That Is Unifying JavaScript

Hello HaWkers, a significant change is happening in the JavaScript ecosystem. Signals, a reactivity pattern that gained popularity in frameworks like Solid, Preact, and Angular, is moving toward becoming a native part of the language through a TC39 proposal.

Let's understand what Signals are, why they matter, and how this standardization can change frontend development.

What Are Signals

Basic Concept

Signals are reactive primitives that represent values that can change over time, automatically notifying whoever depends on them.

Simple analogy:

Think of an Excel spreadsheet. When you change a cell's value, all formulas that depend on that cell are automatically recalculated. Signals work the same way in code.

Main components:

  1. Signal: A reactive value that can be read and written
  2. Computed: A derived value that automatically recalculates when dependencies change
  3. Effect: A function that executes when signals it reads change

Basic example:

// Creating a signal
const count = signal(0);

// Reading the value
console.log(count.value); // 0

// Updating the value
count.value = 1;

// Computed: derived value
const doubled = computed(() => count.value * 2);
console.log(doubled.value); // 2

// Effect: reacts to changes
effect(() => {
  console.log(`Count is now: ${count.value}`);
});

count.value = 5; // Automatically logs: "Count is now: 5"

Why Signals Are Gaining Popularity

Problems Signals Solve

Previous reactivity models had limitations that Signals address.

React model (Virtual DOM) limitations:

Problem Description
Excessive re-render Entire components re-render for any change
Memory overhead Virtual DOM requires tree copy
Complexity useEffect, useMemo, useCallback to optimize
Difficult debugging Update chain can be confusing

Two-Way Binding limitations:

Problem Description
Difficult tracking Hard to know what caused a change
Infinite cycles Possible update loops
Performance Constant change checks

How Signals solve:

  1. Fine granularity: Only what changed is updated
  2. Automatic tracking: Dependencies are detected automatically
  3. No overhead: No Virtual DOM or diffing
  4. Predictability: Clear, unidirectional data flow
  5. Simplicity: Fewer APIs to memorize

Signals in Current Frameworks

Who Already Uses Signals

Several frameworks have adopted Signals as their reactivity model.

Solid.js:

import { createSignal, createEffect } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(0);

  createEffect(() => {
    console.log("Count changed:", count());
  });

  return (
    <button onClick={() => setCount(count() + 1)}>
      Count: {count()}
    </button>
  );
}

Preact Signals:

import { signal, computed } from "@preact/signals";

const count = signal(0);
const doubled = computed(() => count.value * 2);

function Counter() {
  return (
    <button onClick={() => count.value++}>
      Count: {count} (Doubled: {doubled})
    </button>
  );
}

Angular Signals (17+):

import { signal, computed, effect } from '@angular/core';

@Component({
  template: `
    <button (click)="increment()">
      Count: {{ count() }}
    </button>
  `
})
export class Counter {
  count = signal(0);
  doubled = computed(() => this.count() * 2);

  constructor() {
    effect(() => {
      console.log('Count:', this.count());
    });
  }

  increment() {
    this.count.update(v => v + 1);
  }
}

Vue 3 (Composition API):

import { ref, computed, watchEffect } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const doubled = computed(() => count.value * 2);

    watchEffect(() => {
      console.log('Count:', count.value);
    });

    return { count, doubled };
  }
};

The TC39 Proposal for Signals

What Is Being Proposed

TC39 is working to standardize Signals as part of the JavaScript language.

Proposal goals:

  1. Interoperability: Signals from different frameworks can work together
  2. Runtime optimization: Engines can optimize Signals natively
  3. Standardized API: A single way to do reactivity
  4. Unified ecosystem: Libraries can depend on native Signals

Proposed API (preliminary):

// Signal creation
const counter = new Signal.State(0);

// Reading
console.log(counter.get()); // 0

// Writing
counter.set(1);

// Computed
const doubled = new Signal.Computed(() => counter.get() * 2);

// Watcher (similar to effect)
const watcher = new Signal.subtle.Watcher(() => {
  console.log('Something changed!');
});

watcher.watch(counter);

Current status:

Aspect Status
Stage Stage 1 (initial proposal)
Champions Rob Eisenberg, Daniel Ehrenberg
Implementations None native yet
Polyfills Available for experimentation
Forecast 2-3 years to Stage 4

How Signals Work Under the Hood

Tracking Mechanism

Understanding how Signals track dependencies helps use them better.

Basic algorithm:

// Mechanism pseudocode
class Signal {
  #value;
  #subscribers = new Set();

  constructor(initialValue) {
    this.#value = initialValue;
  }

  get value() {
    // When someone reads, register as dependent
    if (currentlyRunningComputation) {
      this.#subscribers.add(currentlyRunningComputation);
    }
    return this.#value;
  }

  set value(newValue) {
    if (this.#value !== newValue) {
      this.#value = newValue;
      // Notify all dependents
      for (const subscriber of this.#subscribers) {
        subscriber.notify();
      }
    }
  }
}

Dependency graph:

  count ─────┬─────> doubled ───> UI
             β”‚
             └─────> effect ───> console.log

When count changes:
1. doubled recalculates
2. effect executes
3. UI updates (only the affected part)

Compared Performance

Signals offer significant performance advantages.

Typical benchmark (operations/second):

Operation Virtual DOM Signals Difference
Simple update 10,000 100,000 10x
List with 1000 items 500 5,000 10x
Batched updates 2,000 50,000 25x
Memory used 100% 30% -70%

Illustrative numbers based on public benchmarks

Impact for Developers

What Changes in Practice

If Signals are standardized, several things change.

For React developers:

  • Different mental model (push vs pull)
  • Fewer optimization hooks needed
  • Possible integration via libraries
  • React may or may not adopt Signals internally

For Vue/Angular developers:

  • Already familiar with similar concepts
  • Migration can be gradual
  • APIs may converge to the standard

For library developers:

  • Common base to build on
  • Less reinventing the wheel
  • Better composability between libraries

Learning Signals Today

If you want to prepare, there are ways to start now.

Options to experiment:

// 1. Preact Signals (works with React too!)
npm install @preact/signals-react

// 2. Solid.js for new projects
npm create solid

// 3. Angular 17+ (native signals)
ng new my-app

// 4. Signal polyfill from the proposal
npm install signal-polyfill

Recommended resources:

  • Official Solid.js documentation
  • Angular blog posts about Signals
  • TC39 proposal on GitHub
  • Preact interactive tutorials

Signals vs Other Approaches

Detailed Comparison

How Signals compare to other ways of managing state.

Signals vs useState (React):

// useState - rerenders entire component
const [count, setCount] = useState(0);

// Signal - updates only where used
const count = signal(0);

Signals vs Redux:

Aspect Redux Signals
Boilerplate High Low
Learning curve High Medium
DevTools Excellent In development
Performance Good (with selectors) Excellent (native)
Scope Global Local or global

Signals vs RxJS:

Aspect RxJS Signals
Complexity High Low
Flexibility Very high Medium
Use cases Complex streams Reactive UI
Curve Steep Gentle

The Future of Reactivity in JavaScript

Trends and Predictions

What we can expect in the coming years.

Framework convergence:

"In 2026, we already see Angular, Vue, Solid, and Preact using Signal variants. TC39 standardization may be the final step to unify the ecosystem."

Possible scenarios:

  1. Native Signals: JavaScript gets Signals as part of the language (2027-2028)
  2. Universal adoption: All major frameworks use Signals
  3. React adapts: React may adopt Signals or create compatible alternative
  4. Tools improve: DevTools evolve for Signals debugging

Implications for Architecture

Signals can change how we structure applications.

Emerging patterns:

  • State machines with Signals
  • Signals + Server Components
  • Signals in Web Workers
  • Signals for animations

Anti-patterns to avoid:

  • Too many Signals (excessive granularity)
  • Ignoring dependency cycles
  • Using Signals for data that doesn't change
  • Not cleaning up effects (memory leaks)

Conclusion

Signals represents a significant evolution in how we think about reactivity in JavaScript. With frameworks converging on this model and a TC39 proposal underway, Signals will likely become the de facto standard for building reactive interfaces. For developers, now is the time to start learning.

Key points:

  1. Signals are reactive primitives with automatic dependency tracking
  2. Already available in Solid, Preact, Angular, and Vue (similar concept)
  3. TC39 proposal seeks to standardize Signals in the language
  4. Superior performance to Virtual DOM in many scenarios
  5. Learning Signals now prepares for the frontend future

The JavaScript ecosystem is moving toward greater consistency and performance. Signals is a central part of that evolution.

For more on JavaScript evolution, read: Pattern Matching in JavaScript: The TC39 Proposal That Will Change Your Code.

Let's go! πŸ¦…

Comments (0)

This article has no comments yet 😒. Be the first! πŸš€πŸ¦…

Add comments