Blog>
Snippets

Implementing a Reactive Store from Scratch

Craft a minimal reactive store without Vuex to manage and distribute state across different components, highlighting the granular reactivity system.
class Store {
  constructor(initialState) {
    this.state = new Proxy(initialState, {
      set: (target, prop, value) => {
        target[prop] = value;
        this.notify(prop);
        return true;
      }
    });
    this.listeners = {};
  }

  subscribe(prop, listener) {
    if (!this.listeners[prop]) {
      this.listeners[prop] = [];
    }
    this.listeners[prop].push(listener);
  }

  notify(prop) {
    if (this.listeners[prop]) {
      this.listeners[prop].forEach((listener) => listener(this.state[prop]));
    }
  }
}
Implementing a reactive store class with a Proxy-based reactive state. It allows components to subscribe to state changes.
const appState = new Store({
  count: 0
});

function increment() {
  appState.state.count += 1;
}

function onCountChange(newValue) {
  document.getElementById('count').textContent = newValue;
}

appState.subscribe('count', onCountChange);
Creating an instance of the store with initial state and defining functions to mutate state and to handle state changes.
<div>
  <span id="count">0</span>
  <button onclick="increment()">Increment</button>
</div>
Defining HTML structure with a span to display the count and a button to trigger increment function.
body {
  font-family: Arial, sans-serif;
}

button {
  margin-top: 10px;
  padding: 5px 15px;
}
Adding minimal CSS styling for the body and the button.