use-s-react
Version:
useS is a minimal yet powerful React hook for managing both local and global state — with zero boilerplate
83 lines (82 loc) • 2.35 kB
JavaScript
import { TypeCheck } from "full-copy";
function isSamePrimitive(a, b) {
return Object.is(a, b);
}
function isSameDate(a, b) {
return a.getTime() === b.getTime();
}
function isSameRegExp(a, b) {
return a.source === b.source && a.flags === b.flags;
}
function isSameSet(a, b) {
if (a.size !== b.size)
return false;
for (const item of a) {
if (!b.has(item))
return false;
}
return true;
}
function isSameMap(a, b) {
if (a.size !== b.size)
return false;
for (const [key, val] of a) {
if (!b.has(key) || !Object.is(val, b.get(key)))
return false;
}
return true;
}
function isSameArray(a, b) {
return a.length === b.length && a.every((val, i) => Object.is(val, b[i]));
}
function hasMeaningfulChange(current, patch) {
for (const key in patch) {
const patchVal = patch[key];
const currentVal = current[key];
if (typeof patchVal === "object" &&
patchVal !== null &&
typeof currentVal === "object" &&
currentVal !== null) {
if (hasMeaningfulChange(currentVal, patchVal)) {
return true;
}
continue;
}
if (!Object.is(patchVal, currentVal))
return true;
}
return false;
}
export function hasChanged(prev, next) {
const typePrev = TypeCheck(prev)[0];
const typeNext = TypeCheck(next)[0];
if (typePrev !== typeNext) {
return { changed: true, type: typeNext };
}
const type = typePrev;
const changed = (() => {
switch (type) {
case "number":
case "string":
case "boolean":
case "undefined":
case "null":
return !isSamePrimitive(prev, next);
case "date":
return !isSameDate(prev, next);
case "regexp":
return !isSameRegExp(prev, next);
case "set":
return !isSameSet(prev, next);
case "map":
return !isSameMap(prev, next);
case "array":
return !isSameArray(prev, next);
case "object":
return hasMeaningfulChange(prev, next);
default:
return false;
}
})();
return { changed, type };
}