Blog>
Snippets

Reactive Effect with Computed Properties

Showcase a reactive effect that depends on computed properties and how it automatically updates when dependencies change.
function reactiveEffect(fn) {
  // Reactive system store: tracks dependencies.
  const store = new Map();

  // Track function dependencies.
  function track(key) {
    let deps = store.get(key);
    if (!deps) {
      deps = new Set();
      store.set(key, deps);
    }
    deps.add(effect);
  }

  // Trigger function when dependencies change.
  function trigger(key) {
    const deps = store.get(key);
    if (deps) {
      deps.forEach(effect => effect());
    }
  }

  const effect = () => fn({ track, trigger });
  effect();

  return { track, trigger };
}
Defines the reactiveEffect function that sets up tracking and triggering of reactive dependencies. A store is used to keep track of those dependencies.
// Reactive source object.
const data = { price: 5, quantity: 2 };

// Reactive and computed property store.
let computedStore = {};

// Create reactive effects.
const { track, trigger } = reactiveEffect(() => {
  track('total');
  console.log('Total:', computedStore.total);
});

// Define a computed property with get and set.
Object.defineProperty(computedStore, 'total', {
  get: () => {
    track('price');
    track('quantity');
    return data.price * data.quantity;
  },
  set: (newValue) => {
    console.log('Setting new total:', newValue);
    trigger('total');
  }
});
Creates a simple reactive source object and defines a computed property on a 'computedStore' object. The reactive effect is setup to run when 'total' changes, and the computed property total will recompute when 'price' or 'quantity' changes.
// Update data and see the effect automatically.
data.price = 10;
trigger('price');
Updates the 'price' property of the data object and triggers the reactive effect, which will log the new total to the console due to the dependency.