@bigmi/react
Version:
React primitives for Bitcoin apps.
44 lines • 1.79 kB
JavaScript
'use client';
import { deepEqual } from '@bigmi/core';
import { useMemo, useRef, useSyncExternalStore } from 'react';
const isPlainObject = (obj) => typeof obj === 'object' && !Array.isArray(obj);
export function useSyncExternalStoreWithTracked(subscribe, getSnapshot, getServerSnapshot = getSnapshot, isEqual = deepEqual) {
const trackedKeys = useRef(new Set());
const previousResult = useRef(undefined);
const snapshotCache = useRef(getSnapshot());
const snapshot = useSyncExternalStore((onChange) => subscribe(() => {
snapshotCache.current = getSnapshot();
onChange();
}), () => snapshotCache.current, getServerSnapshot);
const result = useMemo(() => {
if (!isPlainObject(snapshot)) {
return snapshot;
}
const trackedResult = { ...snapshot };
Object.defineProperties(trackedResult, Object.fromEntries(Object.entries(trackedResult).map(([key, value]) => [
key,
{
configurable: false,
enumerable: true,
get: () => {
trackedKeys.current.add(key);
return value;
},
},
])));
return trackedResult;
}, [snapshot]);
return useMemo(() => {
if (!trackedKeys.current.size || !previousResult.current) {
previousResult.current = result;
return result;
}
const hasChanged = Array.from(trackedKeys.current).some((key) => !isEqual(result[key], previousResult.current[key]));
if (!hasChanged) {
return previousResult.current;
}
previousResult.current = result;
return result;
}, [result, isEqual]);
}
//# sourceMappingURL=useSyncExternalStoreWithTracked.js.map