@ui-complex/react-state
Version:
94 lines (91 loc) • 3.04 kB
JavaScript
import { useState, useEffect } from 'react';
function equal(a, b) {
if (a === b)
return true;
if (a && b && typeof a == "object" && typeof b == "object") {
if (a.constructor !== b.constructor)
return false;
var length, i, keys;
if (Array.isArray(a)) {
length = a.length;
if (length != b.length)
return false;
for (i = length; i-- !== 0;)
if (!equal(a[i], b[i]))
return false;
return true;
}
if (a.constructor === RegExp)
return a.source === b.source && a.flags === b.flags;
if (a.valueOf !== Object.prototype.valueOf)
return a.valueOf() === b.valueOf();
if (a.toString !== Object.prototype.toString)
return a.toString() === b.toString();
keys = Object.keys(a);
length = keys.length;
if (length !== Object.keys(b).length)
return false;
for (i = length; i-- !== 0;)
if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
return false;
for (i = length; i-- !== 0;) {
var key = keys[i];
if (!equal(a[key], b[key]))
return false;
}
return true;
}
return a !== a && b !== b;
}
const UICsubscribers = [];
const useSelector = (state, selector) => {
const deepSelector = (state) => typeof selector(state) === "object"
? { ...selector(state) }
: selector(state);
const [s, setState] = useState(deepSelector(state));
useEffect(() => {
const callback = () => {
setState((prev) => {
if (!equal(deepSelector(state), prev)) {
return deepSelector(state);
}
return prev;
});
};
UICsubscribers.push(callback);
return () => {
const index = UICsubscribers.indexOf(callback);
if (index > -1)
UICsubscribers.splice(index, 1);
};
}, [deepSelector]);
return s;
};
const State = ({ state, children, selector, }) => {
const deepSelector = (state) => typeof selector(state) === "object"
? { ...selector(state) }
: selector(state);
const [s, setState] = useState(deepSelector(state));
useEffect(() => {
const callback = () => {
setState((prev) => {
if (!equal(deepSelector(state), prev)) {
return deepSelector(state);
}
return prev;
});
};
UICsubscribers.push(callback);
return () => {
const index = UICsubscribers.indexOf(callback);
if (index > -1)
UICsubscribers.splice(index, 1);
};
}, [deepSelector]);
return children(s);
};
const dispatch = (obj, updater) => {
updater(obj);
UICsubscribers.forEach((callback) => callback());
};
export { State, dispatch, useSelector };