12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- import { useState, useEffect } from "react";
- const shallowEq = (x, y) => x === y;
- export const consoleMonitor = (key, original) => {
- let val = original;
- console.log(`Initializing ${key} with ${JSON.stringify(original)}`);
- return newVal => {
- console.log(`Updating ${key} from ${JSON.stringify(val)} to ${JSON.stringify(newVal)}`);
- }
- }
- export const createStore = (initial, monitor = null) => {
- const get = {};
- const update = {};
- const hooks = {};
- const mergeState = newState => Object.entries(newState).forEach(([key, value]) => {
- const setter = update[key];
- if (setter) {
- setter(value);
- } else {
- let _val = value;
- let _listeners = monitor === null ? [] : [{ callback: monitor(key, value), equality: shallowEq }];
- get[key] = () => _val;
- update[key] = newValue => {
- const oldValue = _val;
- _val = newValue;
- _listeners
- .filter(({ equality }) => !equality(oldValue, newValue))
- .forEach(({ callback }) => callback(newValue));
- }
- const hookName = "use" + key.charAt(0).toUpperCase() + key.slice(1);
- // name allows linters to pick this up as a hook
- const useValue = (equality = shallowEq) => {
- const [val, callback] = useState(_val);
- useEffect(() => {
- _listeners.push({ callback, equality });
- return () => {
- _listeners = _listeners.filter(ln => ln.callback !== callback);
- }
- }, [equality]);
- return val;
- }
- hooks[hookName] = useValue;
- }
- });
- mergeState(initial);
- return [hooks, mergeState, get];
- }
|