Blog

Same Signals, Different Names

Valtteri

Valtteri Luoma

Senior Software Developer

Date

11/11/2025

Frontend components pointing to framework logos, Vue, Angular and Svelte

Modern frontend frameworks are quietly aligning around the same four ideas. Each one gives you a writable cell of state, a way to compute cached values, a place to run effects when values change, and an ergonomic path to wire values to and from the UI.

The vocabulary differs. Angular calls them signals, Vue talks about refs, and Svelte introduces runes, but the mental model is shared. Once you learn the model, you’re moving the same pieces no matter which framework you choose. (Examples at the end of this post.)

The shared model, without the syntax

Think of an application as a set of reactive values. Some are writable and hold your current state. Others are derived and cache their output, recomputing only when their inputs change. Effects bridge this reactive world to I/O, logging, measurement, and the DOM. Two-way bindings close the loop, letting the UI display a value and send changes back through a clear channel. Frameworks differ in how explicit each step is, yet they all provide the same capabilities.

Note: Derived values in these examples are read-only (Vue computed, Angular computed, Svelte $derived, Jotai derived atoms).

What "two-way" actually means

Two-way binding is simply a value paired with a change channel. Inputs in the DOM are the most familiar example: the current value appears on screen and user edits return through an event or binding that updates the state of the application. Component props follow the same pattern when they deliberately expose both the value and a way to report changes. It is a great fit for leaf controls and tight, well-scoped contracts. It is a poor fit for a broad, application-wide state, where a single source of truth and explicit events keep data flow easier to reason about.

Interop patterns that travel well

Moving between these ecosystems is easier when you map each concept directly. A signal or ref corresponds to a simple value that can be read and written. A derived value is a pure function of another state whose result is cached and only recomputed when its inputs change. An effect is code that reacts to state changes  and performs work that isn’t just computing a value. Frameworks differ mainly in when it runs (before or after the UI commits) and how cleanup is handled.

In React, use Jotai atoms for granular derivations, Zustand for a selector-based store, or a signal library like @preact/signals-react if you prefer signals. React itself doesn’t ship signals or two-way binding; use controlled inputs (value + onChange).

Practical guidance for two-way bindings

Treat two-way bindings like sharp tools. Use them to model form controls, sliders, and pickers where the component’s job is to manage a single value and report changes with minimal effort. Prefer explicit inputs and outputs when data should remain controlled by a parent or a store. Keep one source of truth, and make sure every binding flows back to it rather than allowing multiple places to write the same concept.

The takeaway

Although the APIs look different, the core ideas are the same: cells of state, derivations that cache, effects that connect state to the outside world, and a tidy way to wire values to the UI in both directions. Learn this model once and you can translate it anywhere, even when the names change.

Minimal Examples

Vue 3 (Composition API)

Image

Notes: refs for state, computed for memoized derivations, watchEffect for reactive effects. Two-way via v-model on inputs or components.

Angular (Signals)

Image

Notes: Writable signals, cached computed, and effects that re-run on dependency change. Two-way via [input] + (output) (or model() sugar).

Svelte 5 (Runes) — script-only

Image

Notes: $state for cells, $derived for cached derivations, $effect for reactions. Two-way via bind:value and $bindable for parent↔child.

React + Jotai

Image

Notes: In React, components that read an atom re-render when it changes. Wire UI with controlled inputs (value + onChange) if you want visible interaction.

Want to learn more? Get in touch!