Hone logo
Hone
Problems

Vue 3 Reactive Dependency Tracker

This challenge focuses on building a core concept of Vue's reactivity system: creating reactive dependencies. Understanding how Vue tracks and updates values based on their dependencies is fundamental to writing efficient and maintainable Vue applications. You will implement a simplified version of this mechanism.

Problem Description

Your task is to create a function that mimics Vue's ref and computed functionalities to establish reactive dependencies. You need to implement two core pieces:

  1. myRef<T>(value: T): This function will take an initial value and return an object with a value property. This value property should be reactive, meaning any changes to it can be tracked.
  2. myComputed<T>(getter: () => T): This function will take a getter function and return an object with a value property. The value property should be computed based on the getter. Crucially, if the getter depends on any myRef values, the myComputed's value should automatically update whenever those dependencies change.

The goal is to ensure that when a myRef's value changes, any myComputed properties that depend on it are re-evaluated and their value property is updated accordingly.

Examples

Example 1: Basic Ref and Computed

import { myRef, myComputed } from './reactivity'; // Assume these are in a local file

const count = myRef(0);
const doubledCount = myComputed(() => count.value * 2);

console.log(doubledCount.value); // Output: 0

count.value = 5;
console.log(doubledCount.value); // Output: 10

Explanation: Initially, count is 0, so doubledCount is computed as 0 * 2 = 0. When count.value is updated to 5, the myComputed property doubledCount detects the change in its dependency (count.value) and re-evaluates its getter, resulting in 5 * 2 = 10.

Example 2: Multiple Dependencies

import { myRef, myComputed } from './reactivity';

const firstName = myRef('John');
const lastName = myRef('Doe');
const fullName = myComputed(() => `${firstName.value} ${lastName.value}`);

console.log(fullName.value); // Output: John Doe

firstName.value = 'Jane';
console.log(fullName.value); // Output: Jane Doe

lastName.value = 'Smith';
console.log(fullName.value); // Output: Jane Smith

Explanation: fullName depends on both firstName and lastName. When either firstName or lastName changes, fullName is recomputed to reflect the latest values.

Example 3: Computed Without Dependencies (Static)

import { myRef, myComputed } from './reactivity';

const staticValue = myComputed(() => 100);

console.log(staticValue.value); // Output: 100

// Even if other refs change, staticValue should not.
const unrelatedRef = myRef(5);
unrelatedRef.value = 10;

console.log(staticValue.value); // Output: 100

Explanation: staticValue's getter does not access any reactive myRef properties. Therefore, it is computed only once and its value remains static, regardless of other reactive changes.

Constraints

  • The myRef function must return an object with a writable value property.
  • The myComputed function must return an object with a read-only value property.
  • The reactivity system should handle multiple myComputed properties depending on the same myRef.
  • The reactivity system should handle a myComputed property depending on multiple myRef properties.
  • The getter function for myComputed will not receive any arguments.
  • The core reactivity logic should be implemented in TypeScript.

Notes

  • Think about how you will "track" which myComputed properties are currently "listening" to which myRef properties.
  • Consider the lifecycle of a computed property: when does it need to be computed? When does it need to be recomputed?
  • Vue's internal implementation uses Proxies for reactivity. For this challenge, you can use simple object property access and a mechanism to store and trigger updates.
  • The goal is to demonstrate the dependency tracking and update mechanism, not necessarily to be as performant or robust as Vue's actual implementation.
  • You will need to implement the myRef and myComputed functions yourself. The examples assume they are imported from a local file named reactivity.ts.
Loading editor...
typescript