Skip to content

Instantly share code, notes, and snippets.

@artalar
Last active May 28, 2018 03:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artalar/7184057ddc9209c5caf094054e125489 to your computer and use it in GitHub Desktop.
Save artalar/7184057ddc9209c5caf094054e125489 to your computer and use it in GitHub Desktop.
import { createRootPath, immutablePreset } from 'pathon';
const createLogger = id => (...args) => console.log(`ID: ${id}`, ...args);
const pathSome = createRootPath(
// initial state
{ list: [{ id: 0, value: Math.random() }] },
// default setters and getters (for `path` to)
immutablePreset
);
const pathSomeList = pathSome.path('list');
// special method for track only structure of collection
// accept new `get` handler by first argument
// trigger only on `pathSomeList.set()`
// (will not trigger for `pathSomeList.path(key).set()`)
const pathSomeListIds = pathSomeList.shape(state => state.map(({ id }) => id));
// special method for track and memorize computed data
// trigger on `pathSomeList.set()` and `pathSomeList.path(key).set()`
const pathSomeListSum = pathSomeList.map(
state => state.reduce((acc, { value }) => acc + value), // computed
(prevCalc, newCalc) => prevCalc === newCalc // comparator
);
// it effective to watch list and every item separately
const pathSomeListItem0 = pathSomeList.path('0');
pathSome.watch(createLogger('pathSome'));
pathSomeList.watch(createLogger('pathSomeList'));
pathSomeListIds.watch(createLogger('pathSomeListIds'));
pathSomeListSum.watch(createLogger('pathSomeListSum'));
pathSomeListItem0.watch(createLogger('pathSomeListItem0'));
// update store === dynamic expansion
// after this you can `pathSome.path('newField').watch(callback)`
pathSome.set({ newField: true });
// "ID: pathSome ...."
pathSomeListItem0.set({ value: Math.random() });
// "ID: pathSome ...."
// "ID: pathSomeList ...."
// "ID: pathSomeListSum ...."
// "ID: pathSomeListItem0 ...."
// watchers for `pathSomeListIds` will not trigger
// `.set` - is method for "extend" collection, but not modify old elements
// so it doesn't trigger watchers in nested elements
pathSomeList.set([...pathSomeList.get(), { id: 1, value: Math.random() }]);
// "ID: pathSome ...."
// "ID: pathSomeList ...."
// "ID: pathSomeListIds ...."
// "ID: pathSomeListSum ...."
// `.reset` - is method for rewrite collection
// so it will trigger watchers in nested elements
pathSomeList.reset(pathSomeList.get().map(element => ({ ...element, newValue: true })));
// "ID: pathSome ...."
// "ID: pathSomeList ...."
// "ID: pathSomeListIds ...."
// "ID: pathSomeListSum ...."
// "ID: pathSomeListItem0 ...." // <-- your attention
// TODO: `compose`
@artalar
Copy link
Author

artalar commented May 28, 2018

export const immutablePreset = {
  set: (state, payload) => {
    if (state instanceof Map) {
      return new Map([...state, ...payload]);
    } else if (state instanceof Set) {
      return new Set([...state, ...payload]);
    } else if (Array.isArray(state)) {
      return payload; // ?
    } else {
      return { ...state, ...payload };
    }
  },
  setPath: path => (state, payload) => {
    if (state instanceof Map) {
      return new Map(state).set(path, payload);
    } else if (state instanceof Set) {
      const newState = [...state];
      newState[path] = payload;
      return new Set(newState);
    } else if (Array.isArray(state)) {
      const newState = state.slice();
      newState[path] = payload;
      return newState;
    } else {
      return { ...state, [path]: payload };
    }
  },
  get: state => state,
  getPath: path => state => {
    if (state instanceof Map) {
      return state.get(path);
    } else if (state instanceof Set) {
      return [...state][path];
    } else {
      return state[path];
    }
  },
  // optional memorization
  comparator: (prevValue, newValue) => prevValue === newValue
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment