HardJavaScriptTypeScript

Vue Reactivity — reactive() + effect()

VueVue.jsReactivityProxyJavaScript

Vue 3's reactivity system is one of the most elegant pieces of modern frontend engineering. At its core are two primitives:

  • `reactive(obj)` — wraps a plain object in a Proxy that intercepts reads and writes.
  • `effect(fn)` — runs fn immediately and automatically re-runs it whenever a reactive property read inside fn is later mutated.

This is the exact mechanism behind ref, computed, watch, and component re-rendering in Vue 3.

How it works

const state = reactive({ count: 0 });

effect(() => {
  console.log('count is', state.count); // runs immediately → "count is 0"
});

state.count = 1; // triggers the effect → "count is 1"
state.count = 2; // triggers again    → "count is 2"

Implementation Guide

You need three pieces:

PieceRole
activeEffectA global variable pointing to the currently-running effect (or null)
track(target, key)Called on Proxy get — registers activeEffect as a dependency of target[key]
trigger(target, key)Called on Proxy set — re-runs all effects that depend on target[key]
targetMap: WeakMap<target, Map<key, Set<effectFn>>>

Your task

Implement reactive(obj), effect(fn), and _reset() (clears module-level state between tests).

The solve(op, ...args) harness is provided — do not modify it.

Sample tests

Test #1reactive() preserves property values on read
Input: ["get",{"count":10},"count"]
Output: 10
Test #2reactive() reflects property mutations
Input: ["set-and-get",{"count":0},"count",42]
Output: 42
Test #3effect() runs the function exactly once on creation
Input: ["effect-runs-once",null]
Output: 1
Test #4effect() re-runs when a tracked reactive property changes (1 init + 1 trigger = 2)
Input: ["trigger-count",{"count":0}]
Output: 2
Test #5effect() captures the updated reactive value after mutation
Input: ["track-value",{"msg":"hello"},"msg","world"]
Output: "world"