Intro to Signals

Signals are fine-grained reactivity, for everyone — aiming to solve the interop problem between the various JavaScript ecosystems. The proposal to TC39 is currently in Stage 1, and is based on design input from the authors/maintainers of Angular, Bubble, Ember, FAST, MobX, Preact, Qwik, RxJS, Solid, Starbeam, Svelte, Vue, Wiz, and more…


This tutorial is made with tutorialkit,

Who is this for?

There are sort of 3 auidences for working with signals.

  • framework authors (who would keep their existing APIs the same, and swap the internal implementation with Signals)
  • app-developers, who wouldn’t change how they work, they keep using the same APIs
  • and library authors, or folks working in vanilla JavaScript for maximum reach — this tutorial will focus on this audience, as the other ways of using Signals would require choosing a library/framework.

How do you use Signals?

Our goal for this lesson is to make a button that increments a count when clicked.

Starting with this code,

import { Signal } from 'signal-polyfill';
let count = new Signal.State(0);
let element = document.querySelector("#counter");

we see that we have an element passed to our function, but nothing has happened with that element — in this case the element is a button.

First, we’ll need to add an event listener to the element.

import { Signal } from 'signal-polyfill';
let count = new Signal.State(0);
let element = document.querySelector("#counter");
element.addEventListener('click', () =>
count.set(count.get() + 1));

But this alone is not enough. There isn’t a way yet to update the element’s text. In a framework that may happen automatically via a templating system, but in Vanilla JavaScript, we have to do that ourselves, and via

import { Signal } from "signal-polyfill";
import { effect } from "signal-utils/subtle/microtask-effect";
let count = new Signal.State(0);
let element = document.querySelector("#counter");
element.addEventListener('click', () =>
count.set(count.get() + 1));
effect(() => (element.innerHTML = `count is ${count.get()}`));

Here we use the “microtask-effect” from signal-utils. Note that signal-utils is a separate project from the TC39 proposal, and effects are not included in the proposal due to how effect timing can very greatly between libraries and frameworks.

Files
Preparing Environment
  • Installing dependencies
  • Starting http server