|
@@ -2,46 +2,39 @@ import { useState, useEffect } from "react";
|
|
|
|
|
|
const shallowEq = (x, y) => x === y;
|
|
|
|
|
|
-const createObservable = initial => {
|
|
|
- let _val = initial;
|
|
|
- let _listeners = [];
|
|
|
-
|
|
|
- const obs = {
|
|
|
- _get: () => _val,
|
|
|
- _set: newValue => {
|
|
|
- const oldValue = _val;
|
|
|
- _val = newValue;
|
|
|
- _listeners
|
|
|
- .filter(({ equality }) => !equality(oldValue, newValue))
|
|
|
- .forEach(({ callback }) => callback(newValue));
|
|
|
- },
|
|
|
- };
|
|
|
-
|
|
|
- // 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;
|
|
|
- }
|
|
|
-
|
|
|
- return [obs, useValue];
|
|
|
-}
|
|
|
-
|
|
|
export const createStore = (initial, actions = {}) => {
|
|
|
const store = {};
|
|
|
const hooks = {};
|
|
|
const dispatch = {};
|
|
|
const selector = {};
|
|
|
Object.entries(initial).forEach(([key, value]) => {
|
|
|
- const [obs, hook] = createObservable(value);
|
|
|
+ let _val = value;
|
|
|
+ let _listeners = [];
|
|
|
+
|
|
|
+ store[key] = {
|
|
|
+ _get: () => _val,
|
|
|
+ _set: newValue => {
|
|
|
+ const oldValue = _val;
|
|
|
+ _val = newValue;
|
|
|
+ _listeners
|
|
|
+ .filter(({ equality }) => !equality(oldValue, newValue))
|
|
|
+ .forEach(({ callback }) => callback(newValue));
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ // 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;
|
|
|
+ }
|
|
|
const hookName = "use" + key.charAt(0).toUpperCase() + key.slice(1);
|
|
|
- store[key] = obs;
|
|
|
- hooks[hookName] = hook;
|
|
|
+ hooks[hookName] = useValue;
|
|
|
});
|
|
|
Object.entries(actions).forEach(([name, act]) => {
|
|
|
dispatch[name] = (...args) => Object.entries(act(...args)).forEach(([key, newValue]) => store[key]?._set(newValue))
|