"Change the data, the UI updates" — Vue, Solid, and Svelte all deliver that without a virtual DOM by making state reactive. The core is small and clever: wrap an object in a Proxy, record which running effect reads which property (track), and when a property is written, re-run exactly those effects (trigger). No dependency arrays, no manual subscriptions — reading a value is subscribing to it. Building this core is the best way to demystify modern reactivity.
Implement reactiveProxySignals() returning { reactive, effect, computed }. See Vue Reactivity in Depth.
function reactiveProxySignals() {
return { reactive, effect, computed };
}
const { reactive, effect, computed } = reactiveProxySignals();
const state = reactive({ price: 10, qty: 2 });
effect(() => console.log('total', state.price * state.qty)); // logs 'total 20'
state.qty = 3; // re-runs -> 'total 30'
const total = computed(() => state.price * state.qty);
total.value; // 30, cached until price/qty change
effect, a property read records the dependency; a write to that property re-runs every effect that read it.computed is lazy + cached — its getter runs on first .value access, caches, and only recomputes after one of its own dependencies changes; effects reading .value react to it.effect returns a stop(); an effect writing a prop it reads must not loop forever.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.