transmuter-store

0.3.0 • Public • Published

TransmuterStore

A store container that reacts to transmutations of properties of the store itself by emitting events.

Getting started

First, install transmuter-store via:

NPM

npm install transmuter-store

Yarn

yarn add transmuter-store

Basic concept

A TransmuterStore consists of 3 things:

  • The name of the store;
  • The store itself, which could be an object with pre-existing properties as an initial state;
  • The context on which to fire the events on.

By default, a TransmuterStore will fire events on a context element when a property of the store changes. This event is namespaced with the name of the store and the name of the property that changed. For example: if the store is named 'shed' and the property that changed is called items, then the event fired will be shed:items.

How does this work, you ask? The magic of transmuter-store lies in wrapping the store object in a Proxy with a set handler. The set handler is called each time a property of the store is being added or changed. This handler then fires an event on the context element, specifying which property has changed.

transmuter-store provides you with 2 things: the store container that fires the events, and a listener helper function (listen) that eases the setting up of store listeners.

How to use

In its simplest form, you can use transmuter-store like this:

import { TransmuterStore, listen } from 'transmuter-store';

// Set up an initial state for the store
const initialState = {
  items: [1, 2, 3],
  isMenuOpen: false
};

// Create a new store and apply the initial state object. Returns a store with name, context and state properties.
const store = new TransmuterStore('app', initialState);

console.log(store.name); // 'app'
console.log(store.context); // window
console.log(store.state); // State object Proxy, this is where the ✨ magic ✨ happens

// Listener function. This is called when a property changes with the name of the prop, the new value and the old value.
function logger(prop, value, oldValue, state) {
  console.log('property:', prop);
  console.log('new value:', value);
  console.log('old value:', oldValue);
  console.log('new state:', state);
}

// Add a store listener that listens to both the items and isMenuOpen properties and calls the above logger() function`
const listener = listen(store, ['items', 'isMenuOpen'], logger);

// Now when you change a property of the store, the change is logged using the listener function.
store.state.isMenuOpen = true;

// Add new items to array.
// ℹ️ See 'Limitations' below
store.state.items = [...store.state.items, 4];

Limitations

As a set handler of a Proxy only watches direct properties of the object it wraps, changes to nested objects or items in arrays won't propagate to the set handler. Use array/object destructuring for this and assigning the new result directly to the store, or use something like Immutable.js.

Plain JS, does not trigger event:

// This does *not* trigger a TransmuterStore event unfortunately
store.state.items.push(4); // ❌

Plain JS, does trigger event:

// This *does* trigger a TransmuterStore event
store.state.items = [...store.state.items, 4]; // ✅

Using Immutable.js

import { TransmuterStore } from 'transmuter-store';
import { List } from 'immutable';

// Set up state
const initialState = {
  items: List([1, 2, 3]) // Use an Immutable List
};

// Set up store
const store = new TransmuterStore('store', initialState);

// Returns a new List containing the added item and assign it to the store.
store.state.items = store.state.items.push(4); // ✅

Roadmap

  • [ ] Watching nested objects, if possible.
  • [ ] Watching items in arrays, if possible.
  • [ ] Handle store property deletions

Thanks

Heydon Pickering, for inspiring me with Mutilator.js to research and develop this library.

License

TransmuterStore is MIT-licensed.

Readme

Keywords

Package Sidebar

Install

npm i transmuter-store

Weekly Downloads

6

Version

0.3.0

License

MIT

Unpacked Size

10.9 kB

Total Files

8

Last publish

Collaborators

  • ivdwiel