Skip to content

Commit

Permalink
Check individual selected values
Browse files Browse the repository at this point in the history
  • Loading branch information
arnautov-anton committed Dec 8, 2024
1 parent 2a7f072 commit 897e7fd
Showing 1 changed file with 27 additions and 10 deletions.
37 changes: 27 additions & 10 deletions src/store/hooks/useStateStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ const noop = () => {};

export function useStateStore<
T extends Record<string, unknown>,
O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>
O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>,
>(store: StateStore<T>, selector: (v: T) => O): O;
export function useStateStore<
T extends Record<string, unknown>,
O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>
O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>,
>(store: StateStore<T> | undefined, selector: (v: T) => O): O | undefined;
export function useStateStore<
T extends Record<string, unknown>,
O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>
O extends Readonly<Record<string, unknown> | Readonly<unknown[]>>,
>(store: StateStore<T> | undefined, selector: (v: T) => O) {
const wrappedSubscription = useCallback(
(onStoreChange: () => void) => {
Expand All @@ -26,18 +26,35 @@ export function useStateStore<
);

const wrappedSnapshot = useMemo(() => {
let cached: [T, O];
let cachedTuple: [T, O];

return () => {
const current = store?.getLatestValue();
const currentValue = store?.getLatestValue();

if (!currentValue) return undefined;

// store value hasn't changed, no need to compare individual values
if (cachedTuple && cachedTuple[0] === currentValue) {
return cachedTuple[1];
}

const newlySelected = selector(currentValue);

// store value changed but selected values wouldn't have to, double-check selected
if (cachedTuple) {
let selectededAreEqualToCached = true;

if (!current) return undefined;
for (const key in cachedTuple[1]) {
if (cachedTuple[1][key] === newlySelected[key]) continue;
selectededAreEqualToCached = false;
break;
}

if (!cached || cached[0] !== current) {
cached = [current, selector(current)];
return cached[1];
if (selectededAreEqualToCached) return cachedTuple[1];
}

return cached[1];
cachedTuple = [currentValue, newlySelected];
return cachedTuple[1];
};
}, [store, selector]);

Expand Down

0 comments on commit 897e7fd

Please sign in to comment.